首页 > 解决方案 > 使用 dataTaskPublisher 的 Swift API 调用

问题描述

在使用 dataTaskPublisher 和从 API 中提取数据方面取得了各种成功。我遇到的问题是嵌套 JSON。我可以获取简单的 JSON,但是像 Pokemon API 这样嵌套了 JSON 的东西让我着迷。

任何建议都会很棒。onappear: // 获取完成是我挂断的部分。

import SwiftUI
import Combine

struct Pokemon: Codable {
    var cards: Card
}

struct Card: Codable {
    var id: String
    var name: String
}


struct ContentView: View {
    @State private var requests = Set<AnyCancellable>()
    @State var pokemon: Pokemon
    
    var body: some View {
        VStack {
            Text("card name here")
        }
        .onAppear {
            let url = URL(string: "https://api.pokemontcg.io/v1/cards")!
            
            self.fetch(url, defaultValue: [Pokemon]()) {
                self.pokemon = $0
            }
        }
    }
    
    func fetch<T: Decodable>(_ url: URL, defaultValue: T, completion: @escaping (T) -> Void) {
        
        let decoder = JSONDecoder()
        
        URLSession.shared.dataTaskPublisher(for: url)
            .retry(1)
            .map(\.data)
            .decode(type: T.self, decoder: decoder)
            .replaceError(with: defaultValue)
            .receive(on: DispatchQueue.main)
            .sink(receiveValue: completion)
            .store(in: &requests)
    }
}

标签: jsonswiftapiparsingnetworking

解决方案


关键“卡片”是一个对象数组,因此您需要更新 Pokemon 如下

struct Pokemon: Codable {
    var cards : [Card]
}

由于 JSON 的根是字典而不是数组,因此将.onAppear函数更新为

 .onAppear {
        let url = URL(string: "https://api.pokemontcg.io/v1/cards")!
        
        self.fetch(url, defaultValue: Pokemon(cards: [Card(id: "default", name: "default")])) {
            self.pokemon = $0
        }
    }

推荐阅读