我有一个通过观察NotificationCenter
:
NotificationCenter.default.addObserver(self, selector: #selector(observedPosition(_: ), name: "calculatePosition", object: nil)
然后是函数:
@objc func observedPosition(_ notification: NSNotification) {
if let data = notification.object as? Int {
self.sendPosition(from: data)
}
由于这个函数可以在非常短的时间内被多次调用,我想将它添加到队列中,并且只在前一个sendPosition()完成后调用sendPosition()
。
我试过这样的事情,但不知道这是否是正确的方法:
@objc func observedPosition(_ notification: NSNotification) {
let queue = DispatchQueue(label: queueLabel, attributes: [], targer: nil)
queue.sync {
if let data = notification.object as? Int {
self.sendPosition(from: data)
}
}
}
答案 0 :(得分:3)
// MARK: - StackableOperationsQueue performs functions from the stack one by one (serial performing)
class StackableOperationsQueue {
private let semaphore = DispatchSemaphore(value: 1)
private lazy var operations = [QueueOperation]()
private lazy var isExecuting = false
fileprivate func _append(operation: QueueOperation) {
semaphore.wait()
operations.append(operation)
semaphore.signal()
execute()
}
func append(operation: QueueOperation) { _append(operation: operation) }
private func execute() {
semaphore.wait()
guard !operations.isEmpty, !isExecuting else { semaphore.signal(); return }
let operation = operations.removeFirst()
isExecuting = true
semaphore.signal()
operation.perform()
semaphore.wait()
isExecuting = false
semaphore.signal()
execute()
}
}
// MARK: - StackableOperationsCuncurentQueue performs functions from the stack one by one (serial performing) but in cuncurent queue
class StackableOperationsCuncurentQueue: StackableOperationsQueue {
private var queue: DispatchQueue
init(queue: DispatchQueue) { self.queue = queue }
override func append(operation: QueueOperation) {
queue.async { [weak self] in self?._append(operation: operation) }
}
}
// MARK: QueueOperation interface
protocol QueueOperation: class {
var сlosure: (() -> Void)? { get }
var actualityCheckingClosure: (() -> Bool)? { get }
init (actualityCheckingClosure: (() -> Bool)?, serialClosure: (() -> Void)?)
func perform()
}
extension QueueOperation {
// MARK: - Can queue perform the operation `сlosure: (() -> Void)?` or not
var isActual: Bool {
guard let actualityCheckingClosure = self.actualityCheckingClosure,
self.сlosure != nil else { return false }
return actualityCheckingClosure()
}
func perform() { if isActual { сlosure?() } }
init (actualIifNotNill object: AnyObject?, serialClosure: (() -> Void)?) {
self.init(actualityCheckingClosure: { return object != nil }, serialClosure: serialClosure)
}
}
class SerialQueueOperation: QueueOperation {
let сlosure: (() -> Void)?
let actualityCheckingClosure: (() -> Bool)?
required init (actualityCheckingClosure: (() -> Bool)?, serialClosure: (() -> Void)?) {
self.actualityCheckingClosure = actualityCheckingClosure
self.сlosure = serialClosure
}
}
class TEST {
private lazy var stackableOperationsQueue: StackableOperationsCuncurentQueue = {
let queue = DispatchQueue(label: "custom_queue", qos: .background,
attributes: [.concurrent], autoreleaseFrequency: .workItem, target: nil)
return StackableOperationsCuncurentQueue(queue: queue)
}()
private func addOperationToQueue(closure: (() -> Void)?) {
let operation = SerialQueueOperation(actualIifNotNill: self) { closure?() }
stackableOperationsQueue.append(operation: operation)
print("!!!! Function added ")
}
private func simpleFunc(index: Int) {
print("Func \(index) started")
sleep(UInt32(index+1));
print("Func \(index) ended")
}
func run() {
(0...3).forEach { index in
addOperationToQueue { [weak self] in self?.simpleFunc(index: index) }
}
}
}
let test = TEST()
test.run()
// qos: .background
!!!! Function added
!!!! Function added
!!!! Function added
!!!! Function added
Func 0 started
Func 0 ended
Func 1 started
Func 1 ended
Func 2 started
Func 2 ended
Func 3 started
Func 3 ended
// qos: .userInitiated
!!!! Function added
Func 0 started
!!!! Function added
!!!! Function added
!!!! Function added
Func 0 ended
Func 1 started
Func 1 ended
Func 2 started
Func 2 ended
Func 3 started
Func 3 ended
答案 1 :(得分:1)
这是正确的,只要您确保使用相同的or
来安排所有queue
方法调用。例如,如果这个sendPosition
是一个局部变量,那么根本没用。