我们的应用程序目前使用NSOperation (Operation in Swift)来管理网络请求和数据解析的序列。某些代码需要在队列中的所有5项操作完成后执行,这通常是用GCD组实现的。
DispatchQueue.global().async {
(0...5).forEach(){
self.queue.addOperation(CustomOperation(value: $0))
}
self.queue.waitUntilAllOperationsAreFinished()
print("All Tasks Done")
}问题是,在所有5个操作完成之前,NSOperation实例不是deinit,这导致内存释放的时间比预期的晚。如果删除queue.waitUntilAllOperationsAreFinished,则实例将立即为deinit。
我们已经添加了自动释放池来避免它。但是,当使用NSOperation时,是否可以立即使waitUntilAllOperationsAreFinished实例成为waitUntilAllOperationsAreFinished?
用waitUntilAllOperationsAreFinished打印
Begin Task 5
Begin Task 4
Begin Task 3
Begin Task 2
Begin Task 1
Begin Task 0
Finish Task 0
Finish Task 1
Finish Task 2
Finish Task 3
Finish Task 4
Finish Task 5
deinit 0
deinit 1
deinit 2
deinit 3
deinit 4
deinit 5
All Tasks Done无waitUntilAllOperationsAreFinished打印
All Tasks Done
Begin Task 0
Begin Task 1
Begin Task 4
Begin Task 3
Begin Task 5
Finish Task 0
Begin Task 2
deinit 0
Finish Task 1
deinit 1
Finish Task 2
deinit 2
Finish Task 3
deinit 3
Finish Task 4
deinit 4
Finish Task 5
deinit 5定制操作。
class CustomOperation: Operation {
public enum State {
case ready
case running
case finished
}
private var state: State = .ready
override var isAsynchronous: Bool { return true }
override open var isExecuting: Bool { state == .running }
override open var isFinished: Bool { state == .finished }
var value: Int = 0
init(value: Int) {
super.init()
self.value = value
}
override func main() {
print("Begin Task \(value)")
DispatchQueue.global().asyncAfter(deadline: .now()+DispatchTimeInterval.seconds(value)) {
print("Finish Task \(self.value)")
self.finish()
}
}
func finish() {
willChangeValue(forKey: "isExecuting")
willChangeValue(forKey: "isFinished")
state = .finished
didChangeValue(forKey: "isFinished")
didChangeValue(forKey: "isExecuting")
}
deinit {
print("deinit")
}
}发布于 2021-09-15 05:37:29
我不知道你的行为,但我不认为你能在这里做点什么。
如果您关心操作顺序,可以将队列设置为有一个maxConcurrentOperationCount为1,这样就可以保持顺序。
如果您关心内存,并且您有一些巨大的数据,您可以在finish()方法中去掉这些数据,或者使用completionBlock来传递它。
还有在OperationQueue属性上使用KVO的选项,它的大多数属性都与KVO和KVC兼容,您可以在其中一些属性上设置观察以触发回调。
如果您正在部署目标>=13,您可以使用组合体,就像已经由vadian编写的那样。
发布于 2021-09-15 04:58:26
一个比等待更好的方法是,例如观察操作计数。
import Combine
DispatchQueue.global().async {
(0...5).forEach {
queue.addOperation(CustomOperation(value: $0))
}
}
var store : AnyCancellable?
store = queue.publisher(for: \.operationCount)
.sink { value in
if value == 0 { print("All Tasks Done")}
}我的建议是联合使用,它也可以与传统的KVO
https://stackoverflow.com/questions/69186928
复制相似问题