首页 > 解决方案 > 在 Swift 5 中使用 Decodables 在一个页面上执行多个 API 请求

问题描述

我用来获取加载decodablea 后需要点击的 URL 列表。TableView

这是我获取 URL 的结构:

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()
}

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

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呢?

标签: swiftdecodable

解决方案


首先你的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()
}

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


推荐阅读