首先说一下,我是从读者的角度来写着篇文章。整篇文章通俗易懂。
在我们上次的项目里开始,首先明白一点,Swift是面向协议的编程,它里面Class是很少的。用的比较多的是protocol,然后在里面进行拓展extension,使用struct
以上都是废话。下面开始干货
首先我们在Podfile 里面输入以下代码添加库,不指定版本就是最新版本
pod 'Alamofire'
pod 'SwiftyJSON'
pod 'HandyJSON'
然后在Podfile的所在目录下运行命令行工具 pod update ,这可能多花些时间,然后 pod install (必做)
接口我这里已经准备好了,看我文章的同学,可以自备接口,只要是JSON格式就好,基本操作都一样。
这里的BASE_URL你可以写在工具类里面
let BASE_URL = "https://xxxxxxxxxxx.com"
接下来写我们的协议,我把它命名为NetworkTool.swift,这是第一步
protocol NetworkToolProtocol{
//我的数据
static func loadMyData()
//我的关注数据
static func loadMyConcern()
}
然后是我们的重头戏extension,这是第二步
extension NetworkToolProtocol{
//我的数据,这里面主要写我们的网络请求逻辑,每一行都有注释,看起来更轻松。
static func loadMyData(){
//这是具体的url
let url = BASE_URL + "/user/info/"
//这是我们的参数,意思一下
let params = ["user_id":user_id]
//这里有的xcode可能不会有提示,第一个参数是url,第二个是请求参数
Alamofire.request(url,parameters:params).responseJSON{
//这里是返回的数据也是swift语法,guard守护,简单说一下只有后面的语句是错误的才会执行大括号里面的内容,后面会经常遇到。
(response) in guard response.result.isSuccess else {
return
}
//这里取到我们数据返回的字符串,这里是赋值加判断的if语句
if let value = response.result.value{
//这里我们用SwiftyJSON进行处理数据
let json = JSON(value)
//这里判断数据是否成功,这是返回的一部分JSON数据
{
....
"message" : "success"
....
}
//以下是判断
guard json["message"] == "success" else{
return
}
//这里是赋值加判断的if语句,判断data里面是否是一个字典,并赋值给data
if let data = json["data"].dictionary{
//判断sections里面是否是一个数组,并赋值给sections
if let sections = data["sections"]?.array{
//这里的[[]]() 最外层的[]()代表对象,里面的[]代表MyCellModel类型的数组,这里这段话代表申明一个MyCellModel类型的数组
var sectionArray = [[MyCellModel]]()
//这里是遍历sections数组
for item in sections{
//申明一个MyCellModel类型的对象
var rows = [MyCellModel]()
//取出数组对象存放进入rows
for row in item.arrayObject!{
//字典序列化为对象
let myCellModel = MyCellModel.deserialize(from: row as? NSDictionary)
rows.append(myCellModel!)
}
sectionArray.append(rows)
}
}
}
}
}
}
//我的关注数据
static func loadMyConcern(){
}
}
接下来写我们的struct
struct NetworkTool :NetworkToolProtocol {
}
在我们要获取数据的地方只要这样调用就好了
NetworkTool.loadMyData()
NetworkTool.loadMyConcern()
还没结束,我们网络请求的数据需要返回,这里我们就要用到闭包回调,
在我们的原有代码上更改
protocol NetworkToolProtocol {
//这里面是多出的回调,返回一个MyCellModel对象的数组
static func loadMyData(completionHandler: (_ sections:[[MyCellModel]]) -> ())
........
}
主体代码的修改,下面文章通过 //?????这里修改过??????,来表示修改内容
extension NetworkToolProtocol{
//我的数据,这里面主要写我们的网络请求逻辑,每一行都有注释,看起来更轻松。
//?????这里修改过??????,加入@escaping,swift4.x默认都是非逃逸的,这里加入逃逸的,也是作为安全警告,需要加上
static func loadMyData(completionHandler: @escaping (_ sections:[[MyCellModel]]) -> ()){
//这是具体的url
let url = BASE_URL + "/user/info/"
//这是我们的参数,意思一下
let params = ["user_id":user_id]
//这里有的xcode可能不会有提示,第一个参数是url,第二个是请求参数
Alamofire.request(url,parameters:params).responseJSON{
//这里是返回的数据也是swift语法,guard守护,简单说一下只有后面的语句是错误的才会执行大括号里面的内容,后面会经常遇到。
(response) in guard response.result.isSuccess else {
return
}
//这里取到我们数据返回的字符串,这里是赋值加判断的if语句
if let value = response.result.value{
//这里我们用SwiftyJSON进行处理数据
let json = JSON(value)
//这里判断数据是否成功,这是返回的一部分JSON数据
{
....
"message" : "success"
....
}
//以下是判断
guard json["message"] == "success" else{
return
}
//这里是赋值加判断的if语句,判断data里面是否是一个字典,并赋值给data
if let data = json["data"].dictionary{
//判断sections里面是否是一个数组,并赋值给sections
if let sections = data["sections"]?.array{
//这里的[[]]() 最外层的[]()代表对象,里面的[]代表MyCellModel类型的数组,这里这段话代表申明一个MyCellModel类型的数组
var sectionArray = [[MyCellModel]]()
//这里是遍历sections数组
for item in sections{
//申明一个MyCellModel类型的对象
var rows = [MyCellModel]()
//取出数组对象存放进入rows
for row in item.arrayObject!{
//字典序列化为对象
let myCellModel = MyCellModel.deserialize(from: row as? NSDictionary)
rows.append(myCellModel!)
}
sectionArray.append(rows)
}
//?????这里修改过??????
completionHandler(sectionArray)
}
}
}
}
}
//我的关注数据
static func loadMyConcern(){
}
}
这里我遇到了一个问题,.... does not conform to protocol ....
这里我把拓展里面的方法,放到struct里面。
struct NetworkTool :NetworkToolProtocol {
static func loadMyCellData(completionHandler: @escaping ([[MyCellModel]]) -> ()) {
let url = BASE_URL + "/user/tab/tabs/?"
let params = ["device_id":device_id]
Alamofire.request(url,parameters:params).responseJSON{
(response) in guard response.result.isSuccess else{
return
}
if let value = response.result.value{
let json = JSON(value)
print(json)
guard json["message"] == "success" else{
return
}
if let data = json["data"].dictionary{
print(data)
if let sections = data["sections"]?.array{
var sectionArray = [[MyCellModel]]()
for item in sections{
var rows = [MyCellModel]()
for row in item.arrayObject!{
let myCellModel = MyCellModel.deserialize(from: row as? NSDictionary)
rows.append(myCellModel!)
}
sectionArray.append(rows)
}
completionHandler(sectionArray)
}
}
}
}
}
}
也就是说extension里面的方法可以干掉了,并且在protocol NetworkToolProtocol {} 里面多加了 @escaping
这里面我多加了一个@escaping
static func loadMyCellData(completionHandler: @escaping (_ sections:[[MyCellModel]]) -> ())
接下来是回调方法,
var sections = [[MyCellModel]]()
override func viewDidLoad() {
super.viewDidLoad()
.......
//这里的self代表控制器
NetworkTool.loadMyCellData { (sections) in
//这里自定义一个个体
let string = "{\"text\":\"我的关注\",\"grey_text\":\"\"}"
//序列化字符串
let myConcern = MyCellModel.deserialize(from: string)
//定义一个数组
var myConcerns = [MyCellModel]()
//把对象添加到数组里面
myConcerns.append(myConcern!)
//添加到数组对象里面
self.sections.append(myConcerns)
//这里用的是+=
self.sections+=sections
//这里比做的刷新数据(要不然数据显示不出来)
self.tableView.reloadData()
}
}
在显示的时候,MineViewController
这是分组的数据,这里的sections其实是个二维数组
override func numberOfSections(in tableView: UITableView) -> Int {
return sections.count
}
这里tableView里面有几行View
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return sections[section].count
}
这里是显示每一行table数据
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
定义一个TableView
let cell = UITableViewCell(style: .default, reuseIdentifier: "cell")
拿出数据二维数组
let section = sections[indexPath.section]
一维数组,每个对象
let myCellModel = section[indexPath.row]
取出里面的数据
cell.textLabel?.text = myCellModel.text
return cell
}
接下来run,就会出现结果,如果遇到爆红直接Fix,界面上显示出来了。