完成处理程序中的 Swift 泛型

Posted

技术标签:

【中文标题】完成处理程序中的 Swift 泛型【英文标题】:Swift generics in completion handler 【发布时间】:2020-08-22 10:34:31 【问题描述】:

我正在尝试重构 dat fetching func 以使其适用于多种可解码结构类型。

    func fetchData<T: Decodable>(_ fetchRequest: FetchRequestType, completion: @escaping ((Result<T, Error>) -> Void)) 
    guard !isFetching else  return 
    isFetching = true
    
    guard let url = getURL(fetchRequest) else  assertionFailure("Could not compose URL"); return 
    let urlRequest = URLRequest(url: url)
    
    self.session.dataTask(with: urlRequest)  [unowned self] (data, response, error) in
        guard let response = response as? HTTPURLResponse,
            response.statusCode == 200 else 
                self.isFetching = false
                completion(.failure(NSError()))
                return
        

        guard let data = data else  assertionFailure("No data"); return 
        
        if let jsonData = try? JSONDecoder().decode(T.self, from: data) 
            self.isFetching = false
            completion(.success(jsonData))
         else 
            assertionFailure("Could not decode JSON data"); return
        

        
    .resume()
    

但是当我使用其中一种可解码类型从控制器调用函数时,我得到一个编译错误

无法推断通用参数“T”

        networkClient.fetchData(.accountsSearch(searchLogin: text, pageNumber: 1))  [unowned self] result in
        switch result 
            case .success(let dataJSON):
                let accountsListJSON = dataJSON as! AccountsListJSON
                let fetchedAccounts = accountsListJSON.items
                    .map( AccountGeneral(login: $0.login, id: $0.id, avatarURLString: $0.avatarURL, type: $0.type) )
                self.accounts = fetchedAccounts
            
            case .failure(_):
                assertionFailure("Fetching error!")
            
        
    

请帮助我找出发生的事情并解决问题。

【问题讨论】:

【参考方案1】:

如果方法没有可以指定静态类型的返回类型,则必须添加参数

func fetchData<T: Decodable>(_ fetchRequest: FetchRequestType, type: T.Type, completion: @escaping (Result<T, Error>) -> Void)  ...

然后调用它

networkClient.fetchData(.accountsSearch(searchLogin: text, pageNumber: 1), type: AccountsListJSON.self)  [unowned self] result in

并删除垂头丧气的as! AccountsListJSON

【讨论】:

谢谢,但@gcharita 的解决方案提供了更简洁的代码!【参考方案2】:

当您像这样调用fetchData(_:completion:) 函数时,通常可以通过提供result 类型来帮助编译器推断T 类型:

networkClient.fetchData(
    .accountsSearch(searchLogin: text, pageNumber: 1)
)  [unowned self] (result: Result<AccountsListJSON, Error>) in
    ...

【讨论】:

以上是关于完成处理程序中的 Swift 泛型的主要内容,如果未能解决你的问题,请参考以下文章

Swift 中的完成处理程序错误

swift 4中的完成处理程序

For/In 循环中的完成处理程序 - swift

Swift 中的完成处理程序 Firebase 观察者

swift 3 和 Xcode 8 中的完成处理程序错误

在 swift 3 中删除完成处理程序中的 UIActivityIndi​​cator