[英]Reload TableView when API completes w/ MVVM
I am working on an app in Swift 4. I am building my app programmatically - no storyboards. 我正在使用Swift 4开发一个应用程序。我正在以编程方式构建我的应用程序 -没有情节提要。
I have a ViewController that looks like this 我有一个看起来像这样的ViewController
class SearchController: UITableViewController {
private let cellID = "cellID"
fileprivate let searchController = UISearchController(searchResultsController: nil)
fileprivate let viewModel = SearchViewModel(client: DiscogClient())
override func viewDidLoad() {
super.viewDidLoad()
setupSearchBar()
setupTableView()
}
fileprivate func setupSearchBar() -> Void {
navigationItem.hidesSearchBarWhenScrolling = false
navigationItem.searchController = searchController
searchController.searchBar.delegate = self
}
fileprivate func setupTableView() -> Void {
tableView.register(UITableViewCell.self, forCellReuseIdentifier: cellID)
tableView.tableFooterView = UIView()
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return viewModel.cellViewModels.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellID, for: indexPath)
return cell
}
}
extension SearchController: UISearchBarDelegate {
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
viewModel.search(term: searchText)
}
}
And I have a ViewModel that looks like this 我有一个看起来像这样的ViewModel
import Foundation
import UIKit
class SearchViewModel {
var cellViewModels: [Result] = []
private let client: APIClient
var results: SearchResults? {
didSet {
for result in (results?.results)! {
cellViewModels.append(result)
}
}
}
var isLoading: Bool = false {
didSet {
showLoading?()
}
}
var showLoading: (() -> Void)?
var reloadData: (() -> Void)?
var showError: ((Error) -> Void)?
init(client: APIClient) {
self.client = client
}
func search(term: String) {
if let client = client as? DiscogClient {
let endpoint = DiscogsEndpoint.search(term: term, searchType: .release)
client.fetch(with: endpoint) { (either) in
switch either {
case .success(let results):
self.results = results
case .error(let error):
self.showError?(error)
}
}
}
}
}
When I check didSet
on var results: SearchResults?
当我在
var results: SearchResults?
上检查didSet
时var results: SearchResults?
I can see that the value is being set via my APIClient
. 我可以看到该值是通过我的
APIClient
设置的。
What I would to do is instruct my ViewController table to reload it's data once that value is set. 我要做的就是指示ViewController表在设置该值后重新加载其数据。
I am unsure how to achieve this though? 我不确定如何实现这一目标? I thought I could use a
didSet
on cellViewModels and reach out to a method on my ViewController. 我以为我可以在
didSet
上使用didSet
并扩展到ViewController上的方法。 This does not work or I do not understand how to do this yet. 这行不通,或者我不知道如何执行此操作。
I am hoping to see for now, the number of rows be updated via viewModel.cellViewModels.count
within my SearchController 我希望现在看到行数通过SearchController中的
viewModel.cellViewModels.count
更新
You can modify your search
to accept completion block 您可以修改
search
以接受完成阻止
func search(term: String, @escaping completion :() -> ()) {
if let client = client as? DiscogClient {
let endpoint = DiscogsEndpoint.search(term: term, searchType: .release)
client.fetch(with: endpoint) { (either) in
switch either {
case .success(let results):
self.results = results
completion()
case .error(let error):
self.showError?(error)
completion()
}
}
}
}
Finally you can reload tableView 最后,您可以重新加载tableView
self.search(term: "abcd") {
self.tableView.reloadData()
}
People might often ask you to implement protocols
and establish communication between ViewModel and View. 人们可能经常会要求您
implement protocols
并在ViewModel和View之间建立通信。 But whether to use blocks or protocols is always a design implementation details :) 但是,使用块还是协议始终是设计实现的详细信息:)
Hope this helps. 希望这可以帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.