What is the correct way to set outparam NSError from inside an autoreleasepool block?

I have a way like this:

- (void)processAThing:(id)thing error:(NSError * __autoreleasing *)error { @autoreleasepool { // Start processing. // Find some partway through error.. if (error) { *error = [NSError errorWithDomain...]; return NO; } // More processing. } } 

This is broken and crashing because NSError is auto-implemented, and when the return occurs, the pool merges, so the thing that the caller receives is now fictitious.

I know that I can substantially redesign the method to collect all cases of errors outside the autorun block, but I want to understand if there is a correct way to handle the error object in this situation. I cannot select / fire a speculative NSError outside the pool block because the domain and code properties are readonly (and I still think the link will disappear when the method returns).

It solves the problem if I change the method declaration to this:

 - (void)processAThing:(id)thing error:(NSError * __strong *)error 

But then I need to fuss about the call site in a non-standard way, and it seems egregious to make the subscriber pay the price for my internal autoreleasepool.

Any thoughts? Thanks.

+8
ios objective-c automatic-ref-counting autorelease
source share
1 answer

I had this problem. In this case, I think you just need to declare a new strong link immediately before @autoreleasepool and set the method argument immediately after the @autoreleasepool block from this temporary link.

 - (void)processAThing:(id)thing error:(NSError * __autoreleasing *)error { __strong NSError *errOut = nil; @autoreleasepool { // do your stuff and set errOut instead of error } if (error) { *error = errOut; } } 

(typed in the browser, not the error set by the compiler)

As for your premature return, I think you will have to use a jump label (even if it is not).

+7
source share

All Articles