问题描述
我正试图从REST API快速获取GET。当我使用print语句(print(clubs))时,可以看到正确格式的预期响应。但是在VC中却给了我一个空数组。
这是与API对话的代码
extension ClubAPI {
public enum ClubError: Error {
case unkNown(message: String)
}
func getClubs(completion: @escaping ((Result<[Club],ClubError>) -> Void)) {
let baseURL = self.configuration.baseURL
let endPoint = baseURL.appendingPathComponent("/club")
print(endPoint)
API.shared.httpClient.get(endPoint) { (result) in
switch result {
case .success(let response):
let clubs = (try? JSONDecoder().decode([Club].self,from: response.data)) ?? []
print(clubs)
completion(.success(clubs))
case .failure(let error):
completion(.failure(.unkNown(message: error.localizedDescription)))
}
}
}
}
这是VC中的代码
private class Clubviewmodel {
@Published private(set) var clubs = [Club]()
@Published private(set) var error: String?
func refresh() {
ClubAPI.shared.getClubs { (result) in
switch result {
case .success(let club):
print("We have \(club.count)")
self.clubs = club
print("we have \(club.count)")
case .failure(let error):
self.error = error.localizedDescription
}
}
}
}
这是视图控制器代码(在扩展名之前)
class ClubViewController: UIViewController {
private var clubs = [Club]()
private var subscriptions = Set<AnyCancellable>()
private lazy var dataSource = makeDataSource()
enum Section {
case main
}
private var errorMessage: String? {
didSet {
}
}
private let viewmodel = Clubviewmodel()
@IBOutlet private weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
self.subscriptions = [
self.viewmodel.$clubs.assign(to: \.clubs,on: self),self.viewmodel.$error.assign(to: \.errorMessage,on: self)
]
applySnapshot(animatingDifferences: false)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.viewmodel.refresh()
}
}
extension ClubViewController {
typealias DataSource = UITableViewDiffableDataSource<Section,Club>
typealias Snapshot = NSDiffableDataSourceSnapshot<Section,Club>
func applySnapshot(animatingDifferences: Bool = true) {
// Create a snapshot object.
var snapshot = Snapshot()
// Add the section
snapshot.appendSections([.main])
// Add the player array
snapshot.appendItems(clubs)
print(clubs.count)
// Tell the dataSource about the latest snapshot so it can update and animate.
dataSource.apply(snapshot,animatingDifferences: animatingDifferences)
}
func makeDataSource() -> DataSource {
let dataSource = DataSource(tableView: tableView) { (tableView,indexPath,club) -> UITableViewCell? in
let cell = tableView.dequeueReusableCell(withIdentifier: "Clubcell",for: indexPath)
let club = self.clubs[indexPath.row]
print("The name is \(club.name)")
cell.textLabel?.text = club.name
return cell
}
return dataSource
}
}
解决方法
获取clubs
后,您需要将新快照应用于表视图。您当前的订阅者只需将一个值分配给clubs
,仅此而已。
您可以使用sink
订阅者来分配新的clubs
值,然后调用applySnapshot
。您需要确保这在主队列上发生,因此您可以使用receive(on:)
。
self.subscriptions = [
self.viewModel.$clubs.receive(on: RunLoop.main).sink { clubs in
self.clubs = clubs
self.applySnapshot()
},self.viewModel.$error.assign(to: \.errorMessage,on: self)
]