Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/95.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios Swift-如何从RESTAPI解码json_Ios_Swift_Networking_Combine_Urlsession - Fatal编程技术网

Ios Swift-如何从RESTAPI解码json

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<

我正试图从swift中的restapi中获取一个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)))
            }
        }
    }

}
这是视图控制器代码(在扩展之前)

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)
]