Alamofire异步JSON请求在viewDidLoad中未获响应致数据错误求解决方案
解决异步请求数据未就绪就操作的问题
嘿,我完全懂你现在的困扰!你遇到的就是典型的异步网络请求顺序问题——你在viewDidLoad()里发起请求后,立刻就去处理Data数组,但这时候请求还在后台跑,服务器根本没返回数据,自然会出错。
先直接说结论:绝对不要用延迟来解决这个问题!因为你没法预测服务器响应的速度,延迟设短了还是会拿到空数据,设长了会让用户白白等很久,体验极差。正确的做法是利用异步请求的回调机制,等数据真正返回后再处理。
问题出在哪?
你现在的代码里,虽然在responseJSON的.success分支里填充了Data数组,但有两个小问题:
tableView.reloadData()放在了循环内部,每次加一个数据就刷新一次,没必要,而且可能导致UI频繁跳动;- 你大概率在
viewDidLoad()里调用请求函数后,紧接着就去用Data数组做其他操作(比如提前计算长度、刷新UI),但这时候请求还没完成,Data还是空的。
正确的实现方式
所有依赖服务器返回数据的操作,都必须放到请求成功的回调闭包里面,而且更新UI的代码一定要放到主线程(因为Alamofire的回调默认在后台线程)。
修改后的代码如下:
Alamofire.request(url, method: .post, parameters: params, encoding: JSONEncoding.default, headers: headers) .responseJSON { (response: DataResponse) in switch(response.result) { case .success(let value): let json = JSON(value) // 先清空旧数据(如果需要的话) self.Data.removeAll() for index in 0 ..< json["items"].count { let path = json["items"][index] let profile = ProfileModel() profile.name = path["name"].stringValue profile.email = path["email"].stringValue profile.created = path["created"].double! self.Data.append(profile) } // 所有数据填充完成后,在主线程刷新表格 DispatchQueue.main.async { self.tableView.reloadData() } case .failure(let error): print(error) } } // 注意:这里不要写任何依赖Data数组的代码,因为请求还没完成!
额外建议
- 如果你的
Data数组是用来给表格提供数据源的,确保在viewDidLoad()里初始化它(比如Data = []),避免出现空指针; - 可以在请求发起时显示一个加载指示器(比如
UIActivityIndicatorView),请求完成后再隐藏,提升用户体验; - 永远记住:异步操作的后续逻辑,必须写在它的回调闭包里,而不是外部顺序执行。
内容的提问来源于stack exchange,提问作者metage
相关产品推荐
相关产品推荐

