Wan*_*use 8 nsoperation nsoperationqueue ios swift
我有一个Operation子类和操作队列,maxConcurrentOperationCount = 1.
这按顺序执行我的操作,我添加它们是好的,但现在我需要等到所有操作完成后再运行另一个进程.
我正在尝试使用通知组,但是一旦将操作添加到队列中,这就会在for循环中运行,通知组将触发..如何在运行另一个进程之前等待所有操作离开队列?
for (index, _) in self.packArray.enumerated() {
myGroup.enter()
let myArrayOperation = ArrayOperation(collection: self.outerCollectionView, id: self.packArray[index].id, count: index)
myArrayOperation.name = self.packArray[index].id
downloadQueue.addOperation(myArrayOperation)
myGroup.leave()
}
myGroup.notify(queue: .main) {
// do stuff here
}
Run Code Online (Sandbox Code Playgroud)
Rob*_*Rob 25
您可以使用操作依赖项在完成一系列其他操作后启动某些操作:
let operationQueue = OperationQueue()
let completionOperation = BlockOperation {
// do something
}
for object in objects {
let operation = ...
completionOperation.addDependency(operation)
operationQueue.addOperation(operation)
}
OperationQueue.main.addOperation(completionOperation)
Run Code Online (Sandbox Code Playgroud)
一个合适的解决方案是 KVO
首先在循环之前添加观察者(假设queue是OperationQueue实例)
queue.addObserver(self, forKeyPath:"operations", options:.new, context:nil)
Run Code Online (Sandbox Code Playgroud)
然后执行
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if object as? OperationQueue == queue && keyPath == "operations" {
if queue.operations.isEmpty {
// Do something here when your queue has completed
self.queue.removeObserver(self, forKeyPath:"operations")
}
} else {
super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:
在 Swift 4 中更容易
声明一个属性:
var observation : NSKeyValueObservation?
Run Code Online (Sandbox Code Playgroud)
并创建观察者
observation = queue.observe(\.operationCount, options: [.new]) { [unowned self] (queue, change) in
if change.newValue! == 0 {
// Do something here when your queue has completed
self.observation = nil
}
}
Run Code Online (Sandbox Code Playgroud)
由于 iOS13 和 macOS15operationCount已弃用。更换就是观察progress.completedUnitCount。
另一种现代方法是使用 KVO 发布者 Combine
var cancellable: AnyCancellable?
cancellable = queue.publisher(for: \.progress.completedUnitCount)
.filter{$0 == queue.progress.totalUnitCount}
.sink() { _ in
print("queue finished")
self.cancellable = nil
}
Run Code Online (Sandbox Code Playgroud)