ios - SWIFT - 如何解决回调发生得太晚
问题描述
我正在进行网络调用,取回数据,并希望通过向 tableVC 中的 var 提供数据来将该数据用于 tableVC。我遇到的问题是我的回调返回数据太晚了。下面是我的代码。我真的很感激任何建议
来自网络管理器的代码
func getArticles(completion: @escaping PListCompletion) {
guard let url = plistUrlString else { return }
let urlRequest = URLRequest(url: url)
let defaultConfig = URLSessionConfiguration.default
let session = URLSession(configuration: defaultConfig)
let task = session.dataTask(with: urlRequest) { (data, response, error) in
do {
if let data = data {
let articles = try PropertyListDecoder().decode([Articles].self, from: data)
self.callBackOnMainThread(completion: completion, response: .success(response: PlistResponseData(results: articles)))
}
} catch {
print(error)
completion(.failure(error: error))
}
}
task.resume()
}
private func callBackOnMainThread(completion: @escaping PListCompletion, response: PlistResponse) {
DispatchQueue.main.async {
completion(response)
}
}
final class ArticleListProvider {
var articles: [Articles]
convenience init() {
self.init(articles: [])
self.provideArticles { (article) in
self.articles.append(contentsOf: article)
}
}
init(articles: [Articles]) {
self.articles = articles
}
func articleCount() -> Int {
//used for tableVC cells but returning 0
return self.articles.count
}
func articleAtIndex(_ index: Int) -> Articles? {
return articles[index]
}
func provideArticles(completion: @escaping ([Articles]) -> Void) {
ArticleDetailsNetworkManager.sharedInstance.getArticles { [weak self] (response) in
guard let weakSelf = self else { return}
switch response {
case .success(let plistData):
weakSelf.articles = plistData.results
case .failure(let error):
print(error.localizedDescription)
}
completion(weakSelf.articles)
}
}
}
表VC
final class ArticleListController: UITableViewController {
fileprivate let CellIdentifier = "Cell"
fileprivate let articleListProvider: ArticleListProvider
override init(style: UITableViewStyle) {
self.articleListProvider = ArticleListProvider()
super.init(style:style)
}
required init?(coder: NSCoder) {
self.articleListProvider = ArticleListProvider()
super.init(coder: coder)
}
override func viewDidLoad() {
super.viewDidLoad()
setupTableViewCell()
tableView.reloadData()
}
}
extension ArticleListController {
func setupTableViewCell() {
tableView.register(ArticleTableViewCell.self, forCellReuseIdentifier: CellIdentifier)
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
//this is returning 0 when it should be returning the amount of articles from the articleProvider, where the networking call is being made
return articleListProvider.articleCount()
}
我不知道这是否重要,但这适用于 Xcode 9.4,(尽管没有回调),升级到 10.1 后出现此问题
解决方案
这是一种期望的行为,api 调用是异步的,它不会立即返回任何东西。因此,在该 Web 服务返回结果之前,数组计数将为零。
更改您的 init 方法,例如:
convenience init(callback: @escaping () -> Void) {
self.init(articles: [])
self.provideArticles { (article) in
self.articles.append(contentsOf: article)
callback()
}
}
并通过以下方式从您的视图控制器中使用它:
self.articleListProvider = ArticleListProvider{ [weak self]
guard let weakSelf = self else { return}
weakSelf.yourTableView.reloadData()
}
推荐阅读
- linux - 查找在 Linux 主机上运行的 Rancher
- sorting - 如何以不区分大小写的方式对 Solr 字段进行排序
- ansible - 如果文件存在,请不要运行 ansible 命令
- python - 如何使用 CMake 使用 2 个不同版本的 Python
- remote-desktop - How to change own password in a cascaded remote desktop session
- python - 使用 Python 进行密码验证
- java - 使用递归而不是循环打印嵌套数组中的元素
- graphql - 如何在 Shopify 中更新产品变体中的产品选项?
- python - 使用ffmpeg连接音频和视频文件而不编码
- windows - Windows 上的 pyenv - 不被识别为内部或外部命令