How to cancel NSBlockOperation

后端 未结 4 978
粉色の甜心
粉色の甜心 2020-11-30 22:28

I have a long running loop I want to run in the background with an NSOperation. I\'d like to use a block:

NSBlockOperation *operation = [NSBlock         


        
4条回答
  •  小蘑菇
    小蘑菇 (楼主)
    2020-11-30 23:11

    With Swift 5, you can create a cancellable BlockOperation with addExecutionBlock(_:). addExecutionBlock(_:) has the following declaration:

    func addExecutionBlock(_ block: @escaping () -> Void)
    

    Adds the specified block to the receiver’s list of blocks to perform.


    The example below shows how to implement addExecutionBlock(_:):

    let blockOperation = BlockOperation()
    
    blockOperation.addExecutionBlock({ [unowned blockOperation] in
        for i in 0 ..< 10000 {
            if blockOperation.isCancelled {
                print("Cancelled")
                return // or break
            }
            print(i)
        }
    })
    

    Note that, in order to prevent a retain cycle between the BlockOperation instance and its execution block, you have to use a capture list with a weak or unowned reference to blockOperation inside the execution block.


    The following Playground code shows how to cancel a BlockOperation subclass instance and check that there is no retain cycle between it and its execution block:

    import Foundation
    import PlaygroundSupport
    
    PlaygroundPage.current.needsIndefiniteExecution = true
    
    class TestBlockOperation: BlockOperation {
        deinit {
            print("No retain cycle")
        }
    }
    
    do {
        let queue = OperationQueue()
    
        let blockOperation = TestBlockOperation()
        blockOperation.addExecutionBlock({ [unowned blockOperation] in
            for i in 0 ..< 10000 {
                if blockOperation.isCancelled {
                    print("Cancelled")
                    return // or break
                }
                print(i)
            }
        })
    
        queue.addOperation(blockOperation)
    
        Thread.sleep(forTimeInterval: 0.5)
        blockOperation.cancel()
    }
    

    This prints:

    0
    1
    2
    3
    ...
    Cancelled
    No retain cycle
    

提交回复
热议问题