在异步函数中解雇 UIAlertController

问题描述 投票:0回答:2

我正在努力解决以下问题:

我在异步函数中启动一些网络处理:

func upload(
    object: object, 
    context: NSManagedObjectContext
) async -> Dictionary<String,String> {

}

因此,为了通知用户一个耗时的过程刚刚开始,我会显示一个警报控制器:

let alert = UIAlertController(
    title: "Loading", 
    message: "Please wait...", 
    preferredStyle: .alert
)
self.present(alert, animated: true, completion: nil)

在该功能结束时,如果一切按计划进行,我会成功关闭该警报控制器,并显示另一个警报:

alert.dismiss(
    animated: true, 
    completion: {
        let messageAlert = UIAlertController(
            title: "Success", 
            message: "Upload complete", 
            preferredStyle: .alert
        )
        messageAlert.addAction(
            UIAlertAction(
                title: "OK", 
                style: .default, 
                handler: { (action: UIAlertAction) in
                    //
                }
            )
        )
        self.present(
            messageAlert, animated: true, completion: nil
        )
    }
)

但我也想消除该警报并在发生错误时显示新警报,但第一个警报控制器永远不会被消除:

guard dataString.replacingOccurrences(
    of: "\n", 
    with: ""
) != "no valid userID" else {
    error = true
    alert.dismiss(
        animated: true, 
        completion: {
            let messageAlert = UIAlertController(
                title: "Warning", 
                message: "no valid userID received",
                preferredStyle: .alert
            )
            messageAlert.addAction(
                UIAlertAction(
                    title: "OK", 
                    style: .default, 
                    handler: { (action: UIAlertAction) in
                        //
                    }
                )
            )
            self.present(
                messageAlert, 
                animated: true, 
                completion: nil
            )
        }
    )
    returnDic = [
        "result": "error",
        "info": "no valid userID received"
    ]
    return returnDic
}

我只是无法理解为什么我能够在该函数结束时关闭它,但不能在未来的某个地方关闭它。 Xcode 还抱怨如果现在确实正在显示一个新警报,则无法显示新警报..

[Presentation] Attempt to present <UIAlertController: 0x15880a200> on 
    <Project.ContainerViewController: 0x153708290> (
    from <Project.LockerViewController: 0x155018200>) 
    while a presentation is in progress.

我已经尝试与这样的观察者合作:

var error = Bool() {
    didSet {
        alert.dismiss(animated: true)
    }
}

它被调用,但视图不会再次被关闭:/

有什么想法吗?

ios swift asynchronous uialertcontroller
2个回答
0
投票

我找到了解决办法: 问题是该警报控制器的呈现尚未完成,因此当时无法将其关闭。

解决此问题的方法是:

DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
                    alert.dismiss(animated: true)
}

我通过附加一个封闭块来实现这一点

self.present(alert,animated: true) { print("alert controller is visible") }

在解雇时,该文本尚未打印出来;)

我希望这对其他人也有用;)


0
投票

您还可以使用延续来等待警报的呈现和解除。

更多详情这里

extension UIViewController {

  @MainActor
  public func present(_ alert: UIViewController, animated: Bool) async {
    await withCheckedContinuation { continuation in
      present(alert, animated: animated) {
        continuation.resume()
      }
    }
  }

  @MainActor
  public func dismiss(animated: Bool) async {
    await withCheckedContinuation { continuation in
      dismiss(animated: animated) {
        continuation.resume()
      }
    }
  }
}

只需致电

await self.present(alert, animated: true)
await alert.dismiss(animated: true)
© www.soinside.com 2019 - 2024. All rights reserved.