TableView在设置模型数据(topRatedModel(之前重新加载,因此模型保持为零。我用了主踏板,但没用。我该怎么解决这个问题?您可以在以下位置查看我的代码:https://github.com/melisaozturk/MVVM(主要分支机构是最新的(
class MovieViewController: UIViewController {
@IBOutlet weak var tableView: UITableView!
let viewModel = MovieViewModel()
var topRatedModel: MovieTopRatedModel!
var nowPlayingModel: MovieNowPlayingModel!
var popularModel: MoviePopularModel!
override func viewDidLoad() {
super.viewDidLoad()
self.tableRegister()
self.viewModel.getTopRatedData(completion: { [weak self] response in
if let _ = self {return}
self!.topRatedModel = response
}, completionHandler: { [weak self] error in
if let _ = self {return}
})
self.viewModel.getNowPlayingData(completion: { [weak self] response in
if let _ = self {return}
self!.nowPlayingModel = response
}, completionHandler: { [weak self] error in
if let _ = self {return}
})
self.viewModel.getPopularData(completion: { [weak self] response in
if let _ = self {return}
self!.popularModel = response
}, completionHandler: { [weak self] error in
if let _ = self {return}
})
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
private func tableRegister() {
self.tableView.delegate = self
self.tableView.dataSource = self
self.tableView.separatorStyle = .none
self.tableView.tableFooterView = UIView()
self.tableView.separatorStyle = .none
self.tableView.register(UINib(nibName: "MovieCell", bundle: nil), forCellReuseIdentifier: "MovieCell")
}
}
一旦所有数据都完成加载,就需要重新加载表视图。现在,当这些网络操作仍在运行时,您的代码将重新加载表视图。
现在,您有三个网络操作,在它们全部完成之前,您不想重新加载,而且您不知道它们将按哪个顺序完成。
您可以使用DispatchGroup
来帮助您。
在DispatchGroup
上使用notify
,可以在调度组变为空时执行一些代码。
您在处理weak self
时也有一些错误——如果self不是nil,您的代码就会返回。你想要的恰恰相反。
override func viewDidLoad() {
super.viewDidLoad()
self.tableRegister()
let dispatchGroup = DispatchGroup()
dispatchGroup.enter()
self.viewModel.getTopRatedData(completion: { [weak self] response in
if let self = self else {
self.topRatedModel = response
}
dispatchGroup.leave()
}, completionHandler: { [weak self] error in
dispatchGroup.leave()
})
dispatchGroup.enter()
self.viewModel.getNowPlayingData(completion: { [weak self] response in
if let self = self {
self.nowPlayingModel = response
}
dispatchGroup.leave()
}, completionHandler: { [weak self] error in
dispatchGroup.leave()
})
self.viewModel.getPopularData(completion: { [weak self] response in
if let self = self {
self.popularModel = response
}
dispatchGroup.leave()
}, completionHandler: { [weak self] error in
dispatchGroup.leave()
})
dispatchGroup.notify {
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
}
从样式的角度来看,我会使用Result
类型,或者至少使用一个接受(Response?,Error?)
的闭包,而不是使用两个闭包。
Edit:我在建议将async更改为sync时犯了一个错误。正如@Paulw11所指出的,这是错误的,因为它可能会导致主线程被阻塞。
我能想到的一个解决方案是使用DispatchGroups或调度信号量。我个人对DispatchGroups更满意,所以我会给您留下一些关于如何实现它的伪代码:
override func viewDidLoad() {
super.viewDidLoad()
self.tableRegister()
let dispatcher = DispatchGroup()
//for every function that you want to wait for you make an dispatcher.enter()
dispatcher.enter()
self.viewModel.getTopRatedData(completion: { [weak self] response in
if let _ = self {return}
self!.topRatedModel = response
}, completionHandler: { [weak self] error in
if let _ = self {
// when each of the functions has finished running you can write a dispatcher.leave()
dispatcher.leave()
return
}
})
// This code will wait for all dispatcher.leaves() to run in order to execute the following code.
dispatcher.notify(.main){
self.tableView.reloadData()
}
}
我希望我能帮上一点忙。如果你有什么需要澄清的,我很乐意帮忙。