Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the right way to set an NSError outparam from inside an autoreleasepool block?

I have a method 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 crashes, because the NSError is autoreleased, and when the return happens, the pool is drained, so the thing that the caller gets is now bogus.

I know I could significantly redesign the method so I collect all error cases outside the autorelease block, but I want to understand whether there's a correct way of handling the error object in this situation. I can't alloc/init a speculative NSError outside the pool block, because the domain and code properties are readonly (and I still think the reference would 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 around at the call site in a nonstandard way, and this seems egregious to make the caller pay the price for my internal autoreleasepool.

Any thoughts? Thanks.

like image 655
Ben Zotto Avatar asked Jan 23 '13 21:01

Ben Zotto


1 Answers

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

- (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 browser, not error checked by compiler)

As for your premature return, I guess you'll have to use a jump label (even if it's not pretty).

like image 81
Era Avatar answered Sep 29 '22 15:09

Era