使用 Swift 中的 Decodables 在一个页面上执行多个 API 请求 5

Performing multiple API requests on one page using Decodables in Swift 5

我正在使用 decodable 获取 URL 列表,一旦 TableView 加载,我需要点击这些 URL。

这是我获取 URLS 的结构:

struct CharactersUrls: Decodable {
    let characters: [String]
}

struct Characters: Decodable {
    let characters: [String]
}

struct CharacterInfo: Decodable {
    let Id: Int
    let name: String
    let status: String
}

这是我的功能:

    fileprivate func getCharactersUrls() {
    let endpoint  = "https://rickandmortyapi.com/api/episode/\(episodeID ?? "1")"
    guard let url = URL(string: endpoint) else { return }

    URLSession.shared.dataTask(with: url) {(data, response, error) in
        guard let data = data else { return }

        do {
            let charactersUrls = try JSONDecoder().decode(CharactersUrls.self, from: data)
            print("Characters URLS: \(charactersUrls)")

            let endpoints = [charactersUrls]
            print("Endpoints -> \(endpoints)")

        } catch let jsonError {
            print("Error Serializing JSON:", jsonError)
        }

        }.resume()
}

我在控制台中成功打印了 urls:

Endpoints -> [Rick___Morty.CharactersUrls(characters: ["https://rickandmortyapi.com/api/character/1", "https://rickandmortyapi.com/api/character/2", "https://rickandmortyapi.com/api/character/38", "https://rickandmortyapi.com/api/character/87",  "https://rickandmortyapi.com/api/character/338"])]

现在我需要点击每个 url 以从中获取 id, name, status 并将它们加载到 tableView

使用 Decodable 执行此操作的最佳方法是什么?

首先你的CharacterInfo结构是错误的,id是小写的。

要获取所有角色的信息,您需要第二个数据任务。要在所有任务完成时收到通知,请使用 DispatchGroup。为方便起见,status 被解码为枚举。

struct CharactersUrls: Decodable {
    let characters: [URL]
}

enum Status : String, Decodable {
    case dead = "Dead", alive = "Alive"
}

struct CharacterInfo: Decodable {
    let id: Int
    let name: String
    let status: Status
}

var characterInfos = [CharacterInfo]()

fileprivate func getCharactersUrls() {
    let endpoint  = "https://rickandmortyapi.com/api/episode/\(episodeID ?? "1")"
    guard let endPointURL = URL(string: endpoint) else { return }

    let group = DispatchGroup()

    let outertask = URLSession.shared.dataTask(with: endPointURL) { data, response, error in
        guard let data = data else { print(error!); return }

        do {
            let charactersUrls = try JSONDecoder().decode(CharactersUrls.self, from: data)
            print("Characters URLS: \(charactersUrls)")
            for infoURL in charactersUrls.characters {
                group.enter()
                let innertask = URLSession.shared.dataTask(with: infoURL) { data, response, error in
                    defer{ group.leave() }
                    guard let data = data else { print(error!); return }
                    do {
                        let characterInfo = try JSONDecoder().decode(CharacterInfo.self, from: data)
                        characterInfos.append(characterInfo)
                    } catch {
                        print("Error Getting Info for \(infoURL):", error)
                    }

                }
                innertask.resume()
            }
            group.notify(queue: .main) {
                print(characterInfos)
            }

        } catch {
            print("Error Serializing JSON:", error)
        }

    }
    outertask.resume()
}

要在 table 视图中显示 characterInfos 数组,有无数的教程和示例。