你如何呈现 UIAlertControllers 的序列?

Mel*_*ius 1 ios swift uialertcontroller

我有一个应用程序可以一次从服务器下载许多出版物。对于应用程序中已经存在的每个出版物,我想提示用户是否要覆盖现有版本。

是否有任何干净的方式来呈现 UIAlertControllers,以便当用户回答一个时,应用程序呈现下一个?

San*_*ari 5

这是输出

在此处输入图片说明

尽管在随后的语句中调用了两个警报操作,但只有在用户与屏幕上的警报交互后才会显示第二个警报,我的意思是只有在点击确定或取消后。

如果这是您想要的,正如我在评论中提到的,您可以使用最大并发操作为 1 的异步操作和操作队列

这是代码。

首先声明自己的异步操作

struct AlertObject {
    var title : String! = nil
    var message : String! = nil
    var successAction : ((Any?) -> ())! = nil
    var cancelAction : ((Any?) -> ())! = nil
    
    init(with title : String, message : String, successAction : @escaping ((Any?) -> ()), cancelAction : @escaping ((Any?) -> ())) {
        self.title = title
        self.message = message
        self.successAction = successAction
        self.cancelAction = cancelAction
    }
}


class MyAsyncOperation : Operation {
    var alertToShow : AlertObject! = nil
    var finishedStatus : Bool = false
    
    override init() {
        super.init()
    }
    
    override var isFinished: Bool {
        get {
            return self.finishedStatus
        }
        set {
            self.willChangeValue(forKey: "isFinished")
            self.finishedStatus = newValue
            self.didChangeValue(forKey: "isFinished")
        }
    }
    
    override var isAsynchronous: Bool{
        get{
            return true
        }
        set{
            self.willChangeValue(forKey: "isAsynchronous")
            self.isAsynchronous = true
            self.didChangeValue(forKey: "isAsynchronous")
        }
    }
    
    required convenience init(with alertObject : AlertObject) {
        self.init()
        self.alertToShow = alertObject
    }
    
    override func start() {
        if self.isCancelled {
            self.isFinished = true
            return
        }
        DispatchQueue.main.async {
            let alertController = UIAlertController(title: self.alertToShow.title, message: self.alertToShow.message, preferredStyle: .alert)
            alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in
                self.alertToShow.successAction(nil) //pass data if you have any
                self.operationCompleted()
            }))
            alertController.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: { (action) in
                self.alertToShow.cancelAction(nil) //pass data if you have any
                self.operationCompleted()
            }))
            UIApplication.shared.keyWindow?.rootViewController?.present(alertController, animated: true, completion: nil)
        }
    }
    
    func operationCompleted() {
        self.isFinished = true
    }
}
Run Code Online (Sandbox Code Playgroud)

虽然代码看起来很复杂,但本质上很简单。您所做的就是覆盖 Operation的isFinishedisAsynchronous属性。

如果您知道操作队列如何与操作一起工作,那么应该很清楚我为什么要覆盖这些属性。如果你不知道!OperationQueue 利用Operation 的isFinished 属性上的KVO 来启动Operation 队列中下一个依赖操作的执行。

当 OperationQueue 的最大并发操作计数为 1 时,Operation 的 isFinished 标志决定下一个操作何时执行:)

因为用户可能会在警报的某个不同时间范围内采取行动,所以使操作异步(默认操作是同步的)并覆盖 isFinised 属性很重要。

AlertObject 是一个方便的对象,用于保存警报的元数据。您可以修改它以满足您的需要:)

就是这样。现在,无论哪个 viewController 想要显示警报,它都可以简单地使用,但请MyAsyncOperation确保您只有一个 Queue 实例:)

这就是我如何使用它

    let operationQueue = OperationQueue() //make sure all VCs use the same operation Queue instance :)
    operationQueue.maxConcurrentOperationCount = 1
    
    let alertObject = AlertObject(with: "First Alert", message: "Success", successAction: { (anything) in
        debugPrint("Success action tapped")
    }) { (anything) in
        debugPrint("Cancel action tapped")
    }
    
    let secondAlertObject = AlertObject(with: "Second Alert", message: "Success", successAction: { (anything) in
        debugPrint("Success action tapped")
    }) { (anything) in
        debugPrint("Cancel action tapped")
    }

    let alertOperation = MyAsyncOperation(with: alertObject)
    let secondAlertOperation = MyAsyncOperation(with: secondAlertObject)
    operationQueue.addOperation(alertOperation)
    operationQueue.addOperation(secondAlertOperation)
Run Code Online (Sandbox Code Playgroud)

如您所见,我在后续语句中添加了两个警报操作。即使只有在用户关闭当前显示的警报后才会显示该警报:)

希望这可以帮助