我可以将动态 @escapeing(Result<[CLASS], APIError>) 参数传递给我的函数以重用我的代码吗?

Can I pass in a dynamic @escapeing(Result<[CLASS], APIError>) argument to my function to reuse my code?

我是 swift 的新手,有点挣扎。我有几个 GET 查询,它们最终只使用另一个 class(目标 iOS 10.3,Swift 5)做同样的事情。

此方法接收大量数据集,并通过完成处理程序 returns 接收它们。目前我对每种类型多次使用此代码,但我可以想象没有更有效的方法。

CLASS标记唯一的区别:

func getMultiple (completion: @escaping(Result<[CLASS], APIError>) -> Void) {

let data = try JSONDecoder().decode([CLASS].self, from: data!)

这是我的方法:

func getMultiple (completion: @escaping(Result<[CLASS], APIError>) -> Void) {
        do {
            urlRequest.httpMethod = "GET"
            
            let task = URLSession.shared.dataTask(with: urlRequest) {(data, response, error) in
                if let error = error {
                    print("error: \(error)")
                }
                else {
                    if let httpResponse = response as? HTTPURLResponse {
                        switch httpResponse.statusCode {
                        case 200:
                            do {
                                let data = try JSONDecoder().decode([CLASS].self, from: data!)
                                completion(.success(data))
                                return
                            } catch {
                                print("caught: \(error)")
                            }
                            
                        default:
                            do {
                                let data = try JSONDecoder().decode(ServerMessage.self, from: data!)
                                completion(.failure(
                                    APIError(
                                        code: httpResponse.statusCode,
                                        msg: data)
                                    ))
                            } catch {
                                print("caught: \(error)")
                            }
                            return
                        }
                    }
                }
            }
            task.resume()
        }
    }

这正是泛型旨在解决的问题。在您的函数中将“CLASS”替换为通用参数“Item”,其余的应该完全按照您的意愿工作。

func getMultiple<Item: Decodable>(completion: @escaping(Result<[Item], APIError>) -> Void) {
                ^^^^^^^^^^^^^^^^^                               ^^^^

有关更多信息,请参阅 Swift 编程语言中的 Generic Parameters and Arguments

我经常建议在你的函数签名中添加一个额外的参数,以便更容易地传递类型(这类似于 JSONDecoder 的工作方式):

func getMultiple<Item: Decodable>(of: Item.Type = Item.self, completion: @escaping(Result<[Item], APIError>) -> Void) {
                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^

of 参数未在任何地方使用;这只是意味着您可以更轻松地直接在调用中包含类型:

.getMultiple(of: User.self) { user in ... }

添加= Item.self只是意味着如果从上下文中知道类型,则不必传递它,这很方便。