我們的應用程式目前使用NSOperatoin(Swift中的操作)來管理網路請求和資料決議的序列。 有些代碼需要在佇列中的所有5個操作完成后執行,這通常用GCD組實作。
DispatchQueue.global().async {
(0...5) .forEach(){
self.queue.addOperation(CustomOperation(value: $0)
}
self.queue.waitUntilAllOperationsAreFinished()
print("All Tasks Done"/span>)
}
問題在于,NSOperation實體在所有5個操作完成之前不會被洗掉,這導致記憶體釋放的時間比它應該的要晚。
如果queue.waitUntilAllOperationsAreFinished被洗掉,該實體將立即被洗掉。
我們已經添加了自動釋放池來避免它。但是,當使用waitUntilAllOperationsAreFinished時,是否有可能使NSOperation實體立即被deinit?
使用waitUntilAllOperationsAreFinished
Begin Task 5
BeginTask4
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("完成任務(self.value)")
self.finish()
}
}
func finish() {
willChangeValue(forKey: "isExecuting")
willChangeValue(forKey: "isFinished")
狀態 = . finished
didChangeValue(forKey: "isFinished")
didChangeValue(forKey: "isExecuting")
}
deinit {
print("deinit")
}
}
uj5u.com熱心網友回復:
比等待更好的方法是,例如觀察運算元
。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("所有任務完成") }
}
我的建議使用Combine,用傳統的KVO也可以
uj5u.com熱心網友回復:
不知道這種行為,但我不認為你能在這里做什么。
如果你關心操作的順序,你可以設定佇列有一個maxConcurrentOperationCount到1,這樣你就可以保持順序。
如果你關心記憶體,你有一些巨大的資料,你可以在finish()方法中擺脫它,或者使用completionBlock來傳遞它。
還有一個選項是在OperationQueue屬性上使用KVO,它的大多數屬性都符合KVO和KVC的要求,你可以在其中一些屬性上設定觀察來觸發回呼。
如果你正在部署目標>=13,你可以使用vadian已經寫好的Combine.
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/307295.html
標籤:
