大家都知道,在iOS中,每个vc只能同时展示一个AlertController。
即如果不消掉正在展示的AlertController,是无法展示下一个AlertController的。
在不破坏这个原则的前提下,我们可以使用(NS)OperationQueue,来实现 弹框的串行展示。
首先是DelayedOperation,它对Operation做了一个简单的Hack,支持延迟结束Operation,结束时候调用下finisheOperation即可。
import Foundation
class DelayedOperation: Operation {
// MARK: - Override isExecuting and isFinished
fileprivate var _isExecuting: Bool = false
override var isExecuting: Bool {
get {
return _isExecuting
}
set {
willChangeValue(forKey: "isExecuting")
_isExecuting = newValue
didChangeValue(forKey: "isExecuting")
}
}
fileprivate var _isFinished: Bool = false
override var isFinished: Bool {
get {
return _isFinished
}
set {
willChangeValue(forKey: "isFinished")
_isFinished = newValue
didChangeValue(forKey: "isFinished")
}
}
// MARK: - Funtions
func finishOperation() {
isExecuting = false
isFinished = true
}
override func start() {
isExecuting = true
run()
}
/// Subclass should override this
func run() {
}
}
import Foundation
class DelayedOperation: Operation {
// MARK: - Override isExecuting and isFinished
fileprivate var _isExecuting: Bool = false
override var isExecuting: Bool {
get {
return _isExecuting
}
set {
willChangeValue(forKey: "isExecuting")
_isExecuting = newValue
didChangeValue(forKey: "isExecuting")
}
}
fileprivate var _isFinished: Bool = false
override var isFinished: Bool {
get {
return _isFinished
}
set {
willChangeValue(forKey: "isFinished")
_isFinished = newValue
didChangeValue(forKey: "isFinished")
}
}
// MARK: - Funtions
func finishOperation() {
isExecuting = false
isFinished = true
}
override func start() {
isExecuting = true
run()
}
/// Subclass should override this
func run() {
}
}
import Foundation class DelayedOperation: Operation { // MARK: - Override isExecuting and isFinished fileprivate var _isExecuting: Bool = false override var isExecuting: Bool { get { return _isExecuting } set { willChangeValue(forKey: "isExecuting") _isExecuting = newValue didChangeValue(forKey: "isExecuting") } } fileprivate var _isFinished: Bool = false override var isFinished: Bool { get { return _isFinished } set { willChangeValue(forKey: "isFinished") _isFinished = newValue didChangeValue(forKey: "isFinished") } } // MARK: - Funtions func finishOperation() { isExecuting = false isFinished = true } override func start() { isExecuting = true run() } /// Subclass should override this func run() { } }
接下来是主要的Operation类,它用于完成弹框的展示。
class AlertControllerOperation: DelayedOperation {
fileprivate var seqId: Int
fileprivate weak var parentVC: UIViewController?
init(_ seq: Int, _ vc: UIViewController) {
seqId = seq
parentVC = vc
super.init()
}
override func run() {
let vc = UIAlertController(title: "Test", message: "Message", preferredStyle: .alert)
vc.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in
self.finishOperation()
NSLog("DelayedOperation finished seq=%zd", self.seqId)
DispatchQueue.main.asyncAfter(deadline: .now() + 3, execute: {
self.finishOperation()
})
}))
parentVC?.present(vc, animated: true, completion: nil)
}
}
class AlertControllerOperation: DelayedOperation {
fileprivate var seqId: Int
fileprivate weak var parentVC: UIViewController?
init(_ seq: Int, _ vc: UIViewController) {
seqId = seq
parentVC = vc
super.init()
}
override func run() {
let vc = UIAlertController(title: "Test", message: "Message", preferredStyle: .alert)
vc.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in
self.finishOperation()
NSLog("DelayedOperation finished seq=%zd", self.seqId)
DispatchQueue.main.asyncAfter(deadline: .now() + 3, execute: {
self.finishOperation()
})
}))
parentVC?.present(vc, animated: true, completion: nil)
}
}
class AlertControllerOperation: DelayedOperation { fileprivate var seqId: Int fileprivate weak var parentVC: UIViewController? init(_ seq: Int, _ vc: UIViewController) { seqId = seq parentVC = vc super.init() } override func run() { let vc = UIAlertController(title: "Test", message: "Message", preferredStyle: .alert) vc.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in self.finishOperation() NSLog("DelayedOperation finished seq=%zd", self.seqId) DispatchQueue.main.asyncAfter(deadline: .now() + 3, execute: { self.finishOperation() }) })) parentVC?.present(vc, animated: true, completion: nil) } }
调用方法:
//
// ViewController.swift
// AlertControllerQueueDemo
//
// Created by Heyuan Li on 2017/5/22.
// Copyright © 2017年 Heyuan Li. All rights reserved.
//
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let q = OperationQueue()
q.maxConcurrentOperationCount = 1
for i in 0...5 {
let op = AlertControllerOperation(i, self)
/*
if i == 4 {
op.queuePriority = .veryHigh
}
*/
q.addOperation(op)
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
//
// ViewController.swift
// AlertControllerQueueDemo
//
// Created by Heyuan Li on 2017/5/22.
// Copyright © 2017年 Heyuan Li. All rights reserved.
//
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let q = OperationQueue()
q.maxConcurrentOperationCount = 1
for i in 0...5 {
let op = AlertControllerOperation(i, self)
/*
if i == 4 {
op.queuePriority = .veryHigh
}
*/
q.addOperation(op)
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
// // ViewController.swift // AlertControllerQueueDemo // // Created by Heyuan Li on 2017/5/22. // Copyright © 2017年 Heyuan Li. All rights reserved. // import UIKit class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. let q = OperationQueue() q.maxConcurrentOperationCount = 1 for i in 0...5 { let op = AlertControllerOperation(i, self) /* if i == 4 { op.queuePriority = .veryHigh } */ q.addOperation(op) } } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } }