Search code examples
swiftmemory-managementnsoperationnsblockoperation

Swift NSBlockOperation() Leak: cannot make NSBlockOperation() weak


To avoid a memory leak when using NSBlockOperation in Objective-C, we would have to declare the variable as weak to be able to reference the block operation inside the block (to cancel if needed), typically like this:

__weak NSBlockOperation *blockOp  = [NSBlockOperation blockOperationWithBlock:^{
     if (blockOp.cancelled) {
         ...
     }
}];

But in Swift, when I try declare my NSBlockOpeartion as weak, it is always nil.

weak var blockOp = NSBlockOperation()

Without the weak reference, all is fine except it is leaking a little bit of memory each time. How can I reference the block inside the block without leaking memory in Swift?


Solution

  • You can use an explicit capture list to capture an unowned reference to the operation. (This is one of the only times I'd actually suggest using unowned references, since the operation will be retained as long as its block is executing. If you're still uncomfortable with that guarantee, you could use weak instead.)

    let op = NSBlockOperation()
    op.addExecutionBlock { [unowned op] in
        print("hi")
        if op.cancelled { ... }
    }

    Note that this has to be split into two lines, because the variable can't be referenced from its own initial value.