Explicitly add Reference to Closure Capture

Viewed 56

This seems to be the reverse problem to all the Swift closure issues I can find!

I am using NSFilePromiseReceiver to copy files into my app's storage. I would like to do this with a temporary directory, and I like/often use Ole Begemann's temp directory pattern: https://oleb.net/blog/2018/03/temp-file-helper/

So, I would use that like this:

    guard let tempDirectory = TemporaryDirectory() else { return }
            
    promise.receivePromisedFiles(atDestination: temporaryDirectory.url, options: [:],
                                 operationQueue: OperationQueue()) { fileURL, error in
...
    }

I need the temporary directory object to live for the lifetime of the closure here, but the closure does not need it explicitly.

Is there a way to force the directory to be captured by the closure?

If I add [tempDirectory] as a capture list, I get a compiler warning that it is not used, and tests show that it is simply not captured. Calling some needless operation on tempDirectory in the closure works, but that's horrible.

Any ideas?

2 Answers

Just capturing what matt said in the comments (in case he's not in the middle of writing a longer answer). You want withExtendedLifetime:

...       
operationQueue: OperationQueue()) { [tempDirectory] fileURL, error in
    withExtendedLifetime(tempDirectory) { ... }
}

This creates a "usage" of tempDirectory (so you won't get the warning), and ensures that it is not destroyed before the end of the block.

The best you can do is to pair the explicit capture with

_ = tempDirectory

within the closure. It looks more confusing (possibly requiring a comment for clarity) than withExtendedLifetime but it doesn't increase indentation. Neither option is ideal.

Related