iOS如何使用OperationQueue实现弹框依次展示

大家都知道,在iOS中,每个vc只能同时展示一个AlertController。

即如果不消掉正在展示的AlertController,是无法展示下一个AlertController的。

在不破坏这个原则的前提下,我们可以使用(NS)OperationQueue,来实现 弹框的串行展示。

首先是DelayedOperation,它对Operation做了一个简单的Hack,支持延迟结束Operation,结束时候调用下finisheOperation即可。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
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类,它用于完成弹框的展示。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
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)

    }
}

调用方法:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
//
// 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.
    }


}

 

 

Leave a Reply

Your email address will not be published. Required fields are marked *