I have
class BoxSizeViewDetailController: UIViewController {
weak var output: BoxSizeViewDetailControllerOutput?
@objc
private func save() {
SLPWait.show()
Thread.run {
let operation = MoveBoxWithSizeToAssemblyOperation(boxBarcode: self.boxBarcode, assemblyRef: self.assemblyRef, boxSize: self.boxSize)
operation.completion = { [weak self] error in
Thread.main {
SLPWait.hide()
if let error = error {
error.alert()
return
}
self?.output?.didSaved()
self?.pop()
}
}
let operationQueue = OperationQueue()
operationQueue.addOperations(operation, waitUntilFinished: true)
}
}
}
And
class MoveBoxWithSizeToAssemblyOperation: SLPAsyncOperation {
private let boxBarcode: String
private let assemblyRef: String
private let boxSize: BoxSize
var withSize: Bool = false
var completion: ((NSError?) -> Void)?
init(boxBarcode: String, assemblyRef: String, boxSize: BoxSize) {
self.boxBarcode = boxBarcode
self.assemblyRef = assemblyRef
self.boxSize = boxSize
}
deinit {
SLPLog.debug("Deinit", String(describing: self))
}
override func start() {
if isCancelled {
self.finish()
return
}
super.start()
}
override func main() {
defer {
self.finish()
}
let sendSizeOperation = SendSizeOperation(barcode: boxBarcode, boxSize: boxSize)
let moveBoxToAssemblyOperation = MoveBoxToAssemblyOperation(boxBarcode: boxBarcode, assemblyRef: assemblyRef)
sendSizeOperation.completion = { [unowned moveBoxToAssemblyOperation, weak self] error in
//Here is main thread
if let error = error {
moveBoxToAssemblyOperation.cancel()
self?.completion?(error)
}
}
moveBoxToAssemblyOperation.completion = { [weak self] error in
//Here is main thread
self?.completion?(error)
}
moveBoxToAssemblyOperation.addDependency(sendSizeOperation)
let operationQueue = OperationQueue()
operationQueue.qualityOfService = .userInitiated
operationQueue.addOperations([sendSizeOperation, moveBoxToAssemblyOperation], waitUntilFinished: true)
}
}
And
public extension Thread {
class func run(execute: @escaping @convention(block) () -> Void) {
DispatchQueue.global(qos: .userInitiated).async(execute: execute)
}
class func run(execute: DispatchWorkItem) {
DispatchQueue.global(qos: .userInitiated).async(execute: execute)
}
class func main(execute: @escaping @convention(block) () -> Void) {
DispatchQueue.main.async(execute: execute)
}
class func main(execute: DispatchWorkItem) {
DispatchQueue.main.async(execute: execute)
}
}
So the problem is in this part of code
Thread.run {
let operation = MoveBoxWithSizeToAssemblyOperation(boxBarcode: self.boxBarcode, assemblyRef: self.assemblyRef, boxSize: self.boxSize)
operation.completion = { [weak self] error in
Thread.main {
SLPWait.hide()
if let error = error {
error.alert()
return
}
self?.output?.didSaved()
self?.pop()
}
}
let operationQueue = OperationQueue()
operationQueue.addOperations(operation, waitUntilFinished: true)
}
SLPWait.show() and SLPWait.hide() just show and hide an ActivityIndicator.
The operations MoveBoxWithSizeToAssemblyOperation is not dealloceted (sometimes) and sometimes is dealloceted. Why is that?
My way of thinking. Because I use Thread.run to dispatch from main queue, I think I need wait until "MoveBoxWithSizeToAssemblyOperation" completes and handle completion. But "MoveBoxWithSizeToAssemblyOperation" completes and handle "defer { self.finish }" but not deallocated.
My misunderstanding questions:
- I don't understand should I set
waitUntilFinished" = true? Because I blockthread.runand not the main thread thoughMoveBoxToAssemblyOperationcompletes on main thread. Is theMoveBoxToAssemblyOperationblock main thread when completes ? - When I write
Thread.run {should I capture[weak self]or not ? - Why
MoveBoxWithSizeToAssemblyOperationis not deallocated ?