如何表示 nil Error Swift 完成块

Posted

技术标签:

【中文标题】如何表示 nil Error Swift 完成块【英文标题】:how to represent nil Error Swift completion block 【发布时间】:2018-03-28 21:27:34 【问题描述】:

您好,我在 swift 中有一个 Web 服务工作者对象,它将完成块传递给调用者视图控制器。代码如下:

func getFlightData(for airportCode: String, minutesBehind:String, minutesAhead:String, completion: (([Flight], NSError) -> Void)?) 
    var urlComponents = URLComponents()
    urlComponents.scheme = "https"
    urlComponents.host = "xxxxxxx.com"
    urlComponents.path = "/1/airports/"+airportCode+"/flights/flightInfo"
    urlComponents.queryItems = [
        URLQueryItem(name: "city", value: airportCode),
        URLQueryItem(name: "minutesBehind", value: minutesBehind),
        URLQueryItem(name: "minutesAhead", value: minutesAhead)

    ]

    guard let url = urlComponents.url else  fatalError("Could not create URL from components") 
    var request = URLRequest(url: url)
    request.httpMethod = "GET"
    request.setValue("xxxxxxxxx", forHTTPHeaderField: "Authorization")
    let config = URLSessionConfiguration.default
    let session = URLSession(configuration: config)


    let task = session.dataTask(with: request)  (responseData, response, responseError) in
        DispatchQueue.main.async 


            if let error = responseError 

                //completion block???


            

            else if let jsonData = responseData 

                let decoder = JSONDecoder()

                do 
                    let posts = try decoder.decode([Flight].self, from: jsonData)
                    //completion?(posts, nil) ???? what to pass for Error? Successful call
                 catch 
                    self.showError()

                
            

            else 
                //completion block???
                self.showError()
            
        
    
    task.resume()

调用成功时,我在完成块错误参数中传递了什么值。我不能通过 nil,因为 swift 不允许我这样做。有人可以建议一种更好的方法来进行此 API 调用吗?如何发送完成块等。

【问题讨论】:

【参考方案1】:

它不接受nil,因为您的参数NSError 不是可选的。

声明你的方法签名喜欢

func getFlightData(for airportCode: String, minutesBehind:String, minutesAhead:String, completion: (([Flight], NSError?) -> Void)?) 

....


它应该可以工作

【讨论】:

不要使用NSErrorError 协议更灵活,更符合 Swift 的习惯。 这不是问题,我不知道他的其余实现。如果他使用NSError 可能有一些原因 NSError 符合Error,因此任何采用Error 的东西都可以接受NSError。没有理由在 Swift API 中使用 NSError 假设......是的......仍然不知道,只是回答他的问题【参考方案2】:

将完成块声明为采用Error? 而不是NSError,然后您将能够在成功的情况下将nil 传递给它。 ? 是使参数可选的原因,这使得它可以包含 nil。 (另外,使用 Error 而不是 NSError,因为它是惯用的 Swift 错误类型)。

或者,您可以让您的完成块采用 Result 枚举,您可以这样定义:

public enum Result<T> 
    case success(T)
    case error(Error)

    public func unwrap() throws -> T 
        switch self 
        case let .success(ret):
            return ret
        case let .error(error):
            throw error
        
    

然后您可以使用.success.error 情况,具体取决于操作是成功还是失败。

【讨论】:

完成!我的响应数据呢?我该如何发送?万一出现错误? @Ackman Result 类型用于响应数据和错误相互排斥的情况。如果您可能想在出现错误时读取响应数据,请坚持使用元组实现,但使用 Error? 而不是 NSError 我已经做到了,你能在我的代码中告诉我如何进行这些更改吗?我仍然很困惑。我应该保留错误吗?或将 Result 保留在我的完成块中。我对 swift 还很陌生,很难理解这一点 如果您希望能够同时传递响应数据错误,那么就按照您所做的那样做,但是将NSError 替换为Error?。您可以完全按照您所做的那样使用它,除了现在您可以传递nil 而不会出现编译器错误。如果收到错误意味着响应数据不相关(常见情况),则使用Result 枚举代替传递响应错误。 在你的回答中你说“(另外,使用 NSError 而不是 Error,因为它是惯用的 Swift 错误类型)。”您不是说“(另外,使用Error 而不是NSError,因为它是惯用的Swift 错误类型)”吗?

以上是关于如何表示 nil Error Swift 完成块的主要内容,如果未能解决你的问题,请参考以下文章

而委托为 nil 或未实现外围设备:didDiscoverCharacteristicsForService:error: (Corebluetooth, Swift)

使用 NSError 的 Objective C 到 Swift 完成语法

在 Swift 中,我如何避免选项和 nil 对象引用?

从 swift 评估 javascript 函数,在完成处理程序中得到 nil

自定义 NSError 奇怪的行为 Swift

swift中的可选类型