在刷新 table 视图之前,如何获取视图模型中的存储库列表?
How can I get a list of repositories in the view model before the table view is refreshed?
我正在尝试构建一个搜索 GitHub 存储库的应用程序。我正在使用 MVVM 和 Moya。当我调用搜索方法时,我会在服务器响应之前 table 重新加载视图。
所以应用流程应该是:
用户在搜索栏中输入搜索查询。在 SearchViewController
的 searchBarSearchButtonClicked(_:)
调用我的方法进行搜索。该方法在 SearchViewModel
内。所以视图模型的方法触发 RepositoryService
然后 NetworkService
.
我放了一些打印语句来查看执行顺序。在控制台中,我得到:2 3 4 (Here the table view is refreshing) 1
。我尝试在不同的地方使用 GCD,我也尝试使用障碍。在一天结束时,在调用 print(1)
之前,table 视图仍在刷新。
SearchViewController:
extension SearchViewController: UISearchBarDelegate {
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
guard let query = searchBar.text, query.count > 2 else { return }
viewModel.searchRepositories(withQuery: query) { [weak self] in
guard let self = self else { return }
print(4)
print("Reloading...")
self.tableView.reloadData()
}
}
}
SearchViewModel:
var repositories = [Repository]()
func searchRepositories(withQuery query: String, completion: @escaping () -> Void) {
repositories = repositoryService.searchRepositories(withQuery: query)
print(3)
completion()
}
存储库服务:
private var repositories = [Repository]()
func searchRepositories(withQuery query: String) -> [Repository] {
networkService?.searchRepositories(withQuery: query) { [weak self] repositories in
guard let self = self, let repositories = repositories else { return }
self.repositories += repositories
}
print(2)
return self.repositories
}
网络服务:
func searchRepositories(withQuery query: String,
completionHandler: @escaping (([Repository]?) -> Void)) {
provider?.request(.searchRepo(query: query)) { result in
switch result {
case .success(let response):
do {
let repositories = try response.map(SearchResults<Repository>.self)
print(1)
completionHandler(repositories.items)
} catch let error {
print(error.localizedDescription)
}
case .failure(let error):
print(error)
}
}
}
你的问题基本上是你没有正确处理异步请求。
考虑代码:
var repositories = [Repository]()
func searchRepositories(withQuery query: String, completion: @escaping () -> Void) {
repositories = repositoryService.searchRepositories(withQuery: query) // here we are going to create a network request in the background, which takes time.
print(3)
completion() // when you call this, your network request is still trying, so when your tableView refreshes... the data hasn't returned yet.
}
正如您在评论中看到的那样,这里将发生的事情是:
- 调用网络
- 打印(3)
- 完成 -> 重新加载 Table 查看
- 网络响应数据 -> 你什么都不做。
你应该做什么...
func searchRepositories(withQuery query: String, completion: @escaping (SomeResponseType?, Error?) -> Void) {
repositories = repositoryService.searchRepositories(withQuery: query) { response in
completion(results, error)
}
}
您已在别处遵循此模式,但您需要涵盖所有异步请求。
这里也一样:
func searchRepositories(withQuery query: String) -> [Repository] {
networkService?.searchRepositories(withQuery: query) { [weak self] repositories in
guard let self = self, let repositories = repositories else { return }
self.repositories += repositories
}
print(2)
return self.repositories
}
return self.repositories
将在网络调用开始后立即调用,网络请求将没有时间 return 数据。
有关该主题的一些有用资源:
我正在尝试构建一个搜索 GitHub 存储库的应用程序。我正在使用 MVVM 和 Moya。当我调用搜索方法时,我会在服务器响应之前 table 重新加载视图。
所以应用流程应该是:
用户在搜索栏中输入搜索查询。在 SearchViewController
的 searchBarSearchButtonClicked(_:)
调用我的方法进行搜索。该方法在 SearchViewModel
内。所以视图模型的方法触发 RepositoryService
然后 NetworkService
.
我放了一些打印语句来查看执行顺序。在控制台中,我得到:2 3 4 (Here the table view is refreshing) 1
。我尝试在不同的地方使用 GCD,我也尝试使用障碍。在一天结束时,在调用 print(1)
之前,table 视图仍在刷新。
SearchViewController:
extension SearchViewController: UISearchBarDelegate {
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
guard let query = searchBar.text, query.count > 2 else { return }
viewModel.searchRepositories(withQuery: query) { [weak self] in
guard let self = self else { return }
print(4)
print("Reloading...")
self.tableView.reloadData()
}
}
}
SearchViewModel:
var repositories = [Repository]()
func searchRepositories(withQuery query: String, completion: @escaping () -> Void) {
repositories = repositoryService.searchRepositories(withQuery: query)
print(3)
completion()
}
存储库服务:
private var repositories = [Repository]()
func searchRepositories(withQuery query: String) -> [Repository] {
networkService?.searchRepositories(withQuery: query) { [weak self] repositories in
guard let self = self, let repositories = repositories else { return }
self.repositories += repositories
}
print(2)
return self.repositories
}
网络服务:
func searchRepositories(withQuery query: String,
completionHandler: @escaping (([Repository]?) -> Void)) {
provider?.request(.searchRepo(query: query)) { result in
switch result {
case .success(let response):
do {
let repositories = try response.map(SearchResults<Repository>.self)
print(1)
completionHandler(repositories.items)
} catch let error {
print(error.localizedDescription)
}
case .failure(let error):
print(error)
}
}
}
你的问题基本上是你没有正确处理异步请求。
考虑代码:
var repositories = [Repository]()
func searchRepositories(withQuery query: String, completion: @escaping () -> Void) {
repositories = repositoryService.searchRepositories(withQuery: query) // here we are going to create a network request in the background, which takes time.
print(3)
completion() // when you call this, your network request is still trying, so when your tableView refreshes... the data hasn't returned yet.
}
正如您在评论中看到的那样,这里将发生的事情是:
- 调用网络
- 打印(3)
- 完成 -> 重新加载 Table 查看
- 网络响应数据 -> 你什么都不做。
你应该做什么...
func searchRepositories(withQuery query: String, completion: @escaping (SomeResponseType?, Error?) -> Void) {
repositories = repositoryService.searchRepositories(withQuery: query) { response in
completion(results, error)
}
}
您已在别处遵循此模式,但您需要涵盖所有异步请求。
这里也一样:
func searchRepositories(withQuery query: String) -> [Repository] {
networkService?.searchRepositories(withQuery: query) { [weak self] repositories in
guard let self = self, let repositories = repositories else { return }
self.repositories += repositories
}
print(2)
return self.repositories
}
return self.repositories
将在网络调用开始后立即调用,网络请求将没有时间 return 数据。
有关该主题的一些有用资源: