如何在 TableView 重新加载之前设置模型数据
How Set Model Data Before TableView Reload
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")
}
}
编辑:我犯了一个错误,建议将异步更改为同步。这是错误的,因为它可能导致主线程被阻塞,正如@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()
}
}
希望我能帮上一点忙。如果您需要更多说明,我很乐意提供帮助。
所有数据加载完成后,您需要重新加载 table 视图。您的代码现在重新加载 table 视图,而这些网络操作仍然是 运行.
现在,您有三个网络操作,您不想在它们全部完成之前重新加载,并且您不知道它们将按什么顺序完成。
您可以在这里使用 DispatchGroup
来帮助您。
在 DispatchGroup
上使用 notify
你可以在调度组变空时执行一些代码。
您在处理 weak self
时也有一些错误 - 如果 self 不为零,您的代码将 return。你想要的恰恰相反。
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?)
的闭包,而不是使用两个闭包。
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")
}
}
编辑:我犯了一个错误,建议将异步更改为同步。这是错误的,因为它可能导致主线程被阻塞,正如@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()
}
}
希望我能帮上一点忙。如果您需要更多说明,我很乐意提供帮助。
所有数据加载完成后,您需要重新加载 table 视图。您的代码现在重新加载 table 视图,而这些网络操作仍然是 运行.
现在,您有三个网络操作,您不想在它们全部完成之前重新加载,并且您不知道它们将按什么顺序完成。
您可以在这里使用 DispatchGroup
来帮助您。
在 DispatchGroup
上使用 notify
你可以在调度组变空时执行一些代码。
您在处理 weak self
时也有一些错误 - 如果 self 不为零,您的代码将 return。你想要的恰恰相反。
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?)
的闭包,而不是使用两个闭包。