如何在swift 5中的完成块内向用户显示警报

Posted

技术标签:

【中文标题】如何在swift 5中的完成块内向用户显示警报【英文标题】:How to show an alert to the user inside a completion block in swift 5 【发布时间】:2019-07-22 22:19:16 【问题描述】:

我有一个应用程序对网络服务器进行 API 调用。我终于让 API 调用正常工作,现在可以解析服务器返回的 JSON 数据,但我坚持尝试在请求失败时向用户显示警报。例如,我的服务器可以返回 "success": false, "error": "You didn't ask nicely" 显然错误不是真实的,而是可以返回的表示。我只能检查 URLSession.shared.dataTask 的完成块内的错误,但如果我尝试从内部显示警报,我会收到错误,即我无法从 UI 上的后台线程执行任何操作。

现在的代码比较简单……

URLSession.shared.dataTask(with: self.request)  (data, response, error) in 
    if let error = error 
        completion(.failure(error))
        return
    
    //continue on with processing the response...
    completion(.success(fullResponse))
.resume()

然后在我的调用代码中我有...

connector.connect(pin)  (result) in
    switch(result) 
    case .success(let response):
        if let response = response 
            if response.success 
                //do things
             else 
                self.alert(title: "Error while connecting", message: response.error)
            
         
    case .failure(let error):
        self.alert(title: "Unable to connect", message: error)
  

这导致我无法从后台线程对 ui 线程执行任何操作的错误。如果是这种情况,我如何让用户知道 API 调用失败?我必须能够通知用户。谢谢。

【问题讨论】:

【参考方案1】:

您需要将其包装在 DispatchQueue.main.async 中,因为 URLSession.shared.dataTask 的回调发生在后台线程中

DispatchQueue.main.async 
   self.alert(title: "Error while connecting", message: response.error)

同样适用于

self.alert(title: "Unable to connect", message: error)

但最好将所有代码封装在主队列内的alert 函数中,以便放在一个地方

【讨论】:

漂亮!谢谢【参考方案2】:

您可以使用另一种方法,而不是在 connector.connect(pin) 的回调上调用 DispatchQueue.main.async,您也可以在像这样在 dataTask 上调用 completion 块之前这样做。

URLSession.shared.dataTask(with: self.request)  (data, response, error) in 
    if let error = error 
        DispatchQueue.main.async 
            completion(.failure(error))
        
        return
    
    //continue on with processing the response...
    DispatchQueue.main.async 
        completion(.success(fullResponse))
    
.resume()

通过这样做,您在connector.connect(pin) 中的代码将不会被置于末日金字塔中,并且完成块中的所有内容都在主线程上运行。

connector.connect(pin)  result in
    // everything in here is on the main thread now

【讨论】:

美丽。我没有那样想。谢谢楼主! @NeglectedSanity 如果你喜欢它,你可以upvote我的回答。

以上是关于如何在swift 5中的完成块内向用户显示警报的主要内容,如果未能解决你的问题,请参考以下文章

如何在 swift ui 中显示两个警报,一个接着一个

如何防止 Swift 3 中的嵌套完成块?

swift 2.2中api(json)没有数据时如何显示警报

警报框未显示。 X 代码是跳过 Swift 中的警报框代码

UIAlertController 没有立即显示

如何在 ios Swift 的单个警报中访问推送通知、联系人和照片?