Why passing &error instead of error in Cocoa programming?
In Cocoa programming, when dealing with NSError, why we are passin开发者_高级运维g &error to a message instead of error?
NSError *error;
if (![managedObject.managedObjectContext save:&error])
//Code
The save method takes a pointer to a pointer. There's a good explanation on Cocoa Tutorial: Using NSError to Great Effect
Passing Pointers to Pointers
Using the NSError class in the above example is quite simple. I just pass it in and if the call failed for whatever reason I have an NSError object to explain what the problem was. But how does the other side of that call work?
The first part of this is to understand the concept of passing a pointer to a pointer rather than a pointer to an object. Normally when a message is sent, a pointer to the object is being passed in the message. This is denoted with the single asterisk(*) in the method signature such as
-(void)appendString:(NSString*)newString This is different then passing a pointer to a pointer. First, that type of argument is denoted with two asterisk(**) such as:
-(BOOL)save:(NSError**)error Second, the other difference is this allows the receiving method to control what the pointer (that the pointer is pointing to) is referencing. This is arguably one of the more confusing parts of pointer programming but once you get it, it is a very powerful tool. To put it another way, by passing a pointer to the pointer, the receiving method can decide what your variable’s value is. As you can see in my code above, I initialized the error variable to nil. However, if the save call fails, that variable will no longer be nil but will reference an actual NSError object which I can than interrogate.
If you wish to understand how this works, I would suggest the double indirection wikipedia article as a great starting point.
When you call the method, you aren't giving it a pointer to an NSError, you're giving it a place to pass a pointer to an NSError back to you.
I often write
NSError *error = nil;
which makes it a bit more obvious that there nothing (interesting) in error
when you call -save:
. It's just a place you've set aside for the address in memory of an NSError object. If the method encounters an error, it creates an NSError object and writes the address of the object in error
to pass it back to you.
NSError's fields are not settable. its interface is opaque and immutable. therefore, if you were to alloc/init an error, the client could not populate it. thus, the approach is to return a new error (if applicable), also saving you from allocs in every case.
since the return type is already specified by the method, and the error is optional, it makes sense to take this approach to returning the error in idiomatic c syntax.
iow, the client may neither mutate what you pass nor return the error using :(NSError *)outError
, so the "out parameter" form :(NSError**)outError
is applied.
It's the address-of operator; it produces a pointer pointing to the referent. In this case, error is an NSError *,it takes an address to it and may modify error through that pointer to indicate the error that occurred.
精彩评论