views:

1568

answers:

3

This concept seems to trouble me. Why does an NSError object need its pointer passed to a method that is modifying the object? For instance, wouldn't just passing a reference to the error do the same thing?

NSError *anError;
[myObjc doStuff:withAnotherObj error:error];

and then in doStuff:

 - (void)doStuff:(id)withAnotherObjc error:(NSError *)error 
 {
    // something went bad!
    [error doSomethingToTheObject];
 }

Why doesn't the above work like most other object messaging patterns work? Why must instead we use error:(NSError **)error?

+19  A: 

The answer is that in Objective-C a method can only return one value, and this is a case where you want to return two. In C-like languages when you need to return an extra value you ask for a pointer to a value of that type. The NSError** pattern is used when a method returns some value but may also want to return an error object (of type NSError*). A more realistic example would be this:

// The method should return something, because otherwise it could just return
// NSError* directly and the error argument wouldn't be necessary
- (id)doStuff:(id)withAnotherObjc error:(NSError **)error
{
  // Something went bad!
  // The caller might pass NULL for `error` if they don't care about
  // the result, so check for NULL before dereferencing it
  if (error != NULL) *error = [NSError errorWithDomain:...];
  return nil;  // The caller knows to check error if I return nil
}

If you only had an NSError* instead of an NSError** then doStuff would never be able to pass the error object back to its caller.

n8gray
+5  A: 

Alternate statement of what n8gray said:

Because you're not receiving an object to send messages to; you're creating the object and returning it. You generally need the pointer-to-an-NSError *-variable argument because you can only use the return statement on one thing at a time, and you're already using it with NO.

Peter Hosey
+17  A: 

Quite simply:

if you pass a pointer to an object to your function, the function can only modify what the pointer is pointing to.

if you pass a pointer to a pointer to an object then the function can modify the pointer to point to another object.

In the case of NSError, the function might want to create a new NSError object and pass you back a pointer to that NSError object. Thus, you need double indirection so that the pointer can be modified.

rein