Ios Swift-如何从RESTAPI解码json
我正试图从swift中的restapi中获取一个GET。当我使用print语句(print(clubs))时,我看到了正确格式的预期响应。但是在VC中是给我一个空数组 下面是与API对话的代码Ios Swift-如何从RESTAPI解码json,ios,swift,networking,combine,urlsession,Ios,Swift,Networking,Combine,Urlsession,我正试图从swift中的restapi中获取一个GET。当我使用print语句(print(clubs))时,我看到了正确格式的预期响应。但是在VC中是给我一个空数组 下面是与API对话的代码 extension ClubAPI { public enum ClubError: Error { case unknown(message: String) } func getClubs(completion: @escaping ((Result<
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)))
}
}
}
}
这是视图控制器代码(在扩展之前)
class ClubViewController:UIViewController{
私人var俱乐部=[俱乐部]()
私有变量订阅=Set()
private lazy var dataSource=makeDataSource()
枚举部分{
主箱
}
私有变量错误消息:字符串{
迪塞特{
}
}
private let viewModel=ClubViewModel()
@IBOutlet私有弱var表视图:UITableView!
重写func viewDidLoad(){
super.viewDidLoad()
self.subscriptions=[
self.viewModel.$clubs.assign(to:\.clubs,on:self),
self.viewModel.$error.assign(收件人:\.errorMessage,开:self)
]
applySnapshot(动画差异:false)
}
覆盖函数视图将出现(uo动画:Bool){
超级。视图将显示(动画)
self.viewModel.refresh()
}
}
扩展杆可视控制器{
typealias数据源=UITableViewDiffableDataSource
typealias Snapshot=NSDiffableDataSourceSnapshot
func applySnapshot(动画差异:Bool=true){
//创建快照对象。
var snapshot=snapshot()
//添加该部分
snapshot.appendSections([.main])
//添加玩家阵列
快照。附加项目(俱乐部)
打印(俱乐部数)
//告诉数据源有关最新快照的信息,以便它可以更新和设置动画。
应用(快照、动画差异:动画差异)
}
func makeDataSource()->DataSource{
让dataSource=dataSource(tableView:tableView){(tableView,indexath,club)->UITableViewCell?在
let cell=tableView.dequeueReusableCell(标识符为:“ClubCell”,表示:indexath)
let club=self.clubs[indexath.row]
打印(“名称为\(俱乐部名称)”)
cell.textlab?.text=club.name
返回单元
}
返回数据源
}
}
获取俱乐部后,需要将新快照应用于表视图。您当前的订户只需将一个值分配给俱乐部
,仅此而已
您可以使用sink
订户分配新的clubs
值,然后调用applySnapshot
。您需要确保这在主队列上发生,因此可以使用receive(on:)
将值分配给视图控制器中的clubs
后,需要重新加载表视图。您可以在订阅服务器中执行此操作chain@paulw11你是说在数组中?i、 e自助订阅=[self.viewModel…collectionView.reloaddata我假设您使用的是一个可扩散的数据源。您如何使用该数据源中的clubs数组中的数据?当您将值分配给clubs数组时,您如何告知数据源应用新快照?此时,您显示的代码将把检索到的值分配给clubs
但不告诉tableview对其执行任何操作。当发布者fires@Paulw11我刚刚用数据源代码更新了问题的结尾。
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
}
}
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)
]