Swift - 编写一个通用的 HTTP 请求

标签 swift oop generics inheritance urlsession

所以我尝试使用一些普通的 HTTP 请求和 Swift 的新 Decodable 来检索一些数据。协议(protocol)。

问题是我发现我一次又一次地编写非常相似的代码(创建 URL session 、解码数据、完成处理程序等)。

我正在考虑使用泛型或继承进行简化,但不确定如何初始化“泛型对象”。

当前代码:

var response = TypeAResponse()

if let url = URL(string: urlName) {

    let session = URLSession.shared
    var request = URLRequest(url: url)

    let task = session.dataTask(with: request){ (data, response, error) in

        if let data = data {

            do {
                response = try JSONDecoder().decode(TypeAResponse.self, from: data)
                completion(true, TypeAResponse.items)
            } catch let parseError {
                print("parseError: \(parseError.localizedDescription)")
                completion(false, TypeAResponse.items)
            }

        } else {
            print("Error: Data not found")
            completion(false, TypeAResponse.items)
        }
    }

    task.resume()

} else {
    print("Invalid URL")
    completion(false, TypeAResponse.items)
}

但是 TypeAResponse 的结构与 TypeBResponse 不同——它们共享的只是“items”属性。

可以做类似的事情
    func get<T>(generalType: T, completion: GeneralRequest){
        //but how would you initialise generalType?
        //cannot do something like
        var response = T()

    }

作为引用,TypeAResponse 和 TypeBResponse 可能类似于:
struct TypeAResponse: Decodable {
    items: [Track]?
}

struct Track: Decodable {
    //for example
    var name: String?
}

struct TypeBResponse: Decodable {
    items: [Playlist]?
}

struct Playlist: Decodable {
    var name, id, description: String?
}

API 响应:

请参阅 Spotify Web API 引用 - https://developer.spotify.com/documentation/web-api/reference/playlists/get-playlist/

(特别是“获取用户的播放列表”和“获取播放列表的轨道”)

最佳答案

你在这里肯定走在一个很好的轨道上。从具体代码开始总是好的,然后看看如何使它更通用。对于您的具体情况,当您问“您将如何初始化 generalType?”时这正是协议(protocol)允许您做的事情。因此,按照您的方法,您可以编写类似的内容(我尚未对此进行测试;它可能有一些语法错误):

func get<T: Decodable>(generalType: T, completion: @escaping (Result<T, Error>) -> Void {

    let task = session.dataTask(with: request){ (data, response, error) in

        guard let data = data else {
            let err = error ?? ... some default error ...
            completion(.failure(err))
            return
        }

        let result = Result {
            // You know you can call `decode` with it because it's Decodable
            try JSONDecoder().decode(T.self, from: data)
        }
        completion(result)                     
    }
    task.resume()
}

系列 Start With A Protocol可能会有所帮助(感谢那些提到它的人)。它在这个问题上更深入。但是对于简单的应用程序,这个函数可能就是你所需要的,你应该避免增加更多的复杂性,直到它对你有用。

关于Swift - 编写一个通用的 HTTP 请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59777612/

相关文章:

ios - Collection View 单元格未出现

ios - 使用 'YoutubePlayer Swift SDK' 在 tableviewCell 中播放 youtube 视频

java - 我应该如何处理对象关系映射中对象的删除

python - 使用自定义混合类型创建枚举

python - 函数初始化和对象初始化(多处理)

c# - 泛型规则和类型约束

generics - Typescript 中的通用工厂参数

swift - Xcode 9.2 编译速度太慢

ios - 如何使用 Swift 4 实现具有动态键的字典数组的可编码

编译时出现 Java 泛型错误