Mel*_*ius 1 ios swift uialertcontroller
我有一个应用程序可以一次从服务器下载许多出版物。对于应用程序中已经存在的每个出版物,我想提示用户是否要覆盖现有版本。
是否有任何干净的方式来呈现 UIAlertControllers,以便当用户回答一个时,应用程序呈现下一个?
这是输出
尽管在随后的语句中调用了两个警报操作,但只有在用户与屏幕上的警报交互后才会显示第二个警报,我的意思是只有在点击确定或取消后。
如果这是您想要的,正如我在评论中提到的,您可以使用最大并发操作为 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的isFinished和isAsynchronous属性。
如果您知道操作队列如何与操作一起工作,那么应该很清楚我为什么要覆盖这些属性。如果你不知道!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)
如您所见,我在后续语句中添加了两个警报操作。即使只有在用户关闭当前显示的警报后才会显示该警报:)
希望这可以帮助
| 归档时间: |
|
| 查看次数: |
795 次 |
| 最近记录: |