views:

420

answers:

4

There are many Cocoa methods that require an NSError object as a parameter to a method, but are really a means of returning an error object to the calling method if errors exist. Is this returned object retained? That is, in the calling object code (the method to which the error is returned), does there need to be some code like:

  NSError *error;
  [apiCall .... error:&error];

  if (error){
    [*error release];
 }

I haven't seen this anywhere, and if it does need to be released, is this the way to do it?

+3  A: 

Returned objects are generally autoreleased. The general rule is you only call auto-/release if you earlier called copy/alloc/retain on the same object. And you wouldn't dereference error in a method call:

// right
[error code]
// wrong
[*error code]
outis
The reason I put the [*error code] is that you can also specify the NSError var as: NSError **error; Which is a point to a point to the object. Is this valid?
casademora
You specify `NSError **` as a type for `error` only when it's an "out parameter" or "output parameter". In that case you would dereference, but note that `*error` would have type `NSError *`. You use out parameters to get around the fact that functions have only one return value. Out parameters in Objc-C use `Type **` because arguments are pass-by-value. Note also that if `error` had type `NSError **`, you'd have to either initialize it with a pointer to an `NSError *` (which is what you do in the API call) or allocate a pointer, which happens but is a little odd.
outis
+3  A: 

You haven't allocated memory for the error, so you don't need to release it. As a rule, the framework usually adds autorelease to any objects it creates.

Ken Pespisa
+4  A: 

Read the memory rules on developer.apple.com Never trust anyone restating them like 'you earlier called copy/alloc/retain' - this is not the rule, which actually says something like 'you recieved the object via a method with copy, new or alloc as part of the name'. Again, don't trust me, read developer.apple.com

As to NSError * * , thats just wrong. The METHOD takes an NSError * * as its argument, that is a pointer to an NSError * . Its the POINTER TO THE NSError * that will be populated with the address of an NSError that comes from somewhere and you have no right to assume where.

You can only pass a pointer to an NSError * - anything else is wrong.

Nor should you assume the NSError is auto-released. It may be a singleton, it could be any number of alternates. All you need to know is that 'you didn't retain it, you don't need to release it'.

Jeff
The Ownership Policy (http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmObjectOwnership.html#//apple_ref/doc/uid/20000043-SW1) is that methods with copy/alloc/new imply ownership (and retain explicitly declares ownership), which is what determines who sends release messages.
outis
3rd parties aren't required to follow this policy, but Apple's recommendation is to autorelease a created NSError before returning it (http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/ErrorHandlingCocoa/CreateCustomizeNSError/CreateCustomizeNSError.html#//apple_ref/doc/uid/TP40001806-CH204-SW5)
outis
Hence "generally autoreleased" and "general rule".
outis
A: 

Ok but it's not creating this object if you pass it by reference:

NSError *error = nil;

if (![managedObjectContext save:&error]) {
    // Handle the error.
}

In this example you would need to release it...

OOP_Master