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

问题描述

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

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

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

标签: iosswifthttpswift5urlsession

解决方案


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

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

有关更多信息,请参阅Swift 编程语言中的通用参数和参数

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

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

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

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

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


推荐阅读