Reputation: 18745
What is the correct way to handle NSError** pointers?
- (BOOL)handleData:(NSDictionary *)data error:(NSError **)error {
// pass the error pointer to NSJSONSerialization
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:data options:options error:error];
// Check if NSJSONSerialization had errors
if (error) // <-- sometimes this works, sometimes it crashes...
return false;
...
return true;
}
- (void)someMethod {
NSError *error = nil;
BOOL result = [self handleData:dataDict error:&error];
if (error) {
// an error occurred
} else {
}
}
In this example someMethod
passes a NSError
reference to handleData:error
. This is done by passing a pointer/address instead of the object (...error:&error
)
The method handleData:error
then passes this pointer to dataWithJSONObject:options:error
(now without the &
). Now I would like to check an error occurred, but what is the correct way to do this?
if (error)...
// This works if error == nil. However this is not always the case.
// Sometimes error is some address (e.g. 0x600001711f70) and *error == nil
// from the start of the method (passing error to NSJSONSerialization has no
// influence on this
if (*error)...
// This works in cases where error itself is not nil, but it crashes if
// error == nil
Why is error == nil
in some cases and error != nil
but *error == nil
in others?
What is the correct way to pass error between the methods and to check if an error occurred?
Upvotes: 1
Views: 967
Reputation: 53010
The place to find the answers is Introduction to Error Handling Programming Guide For Cocoa. The conventions are:
A method may return an NSError
object via an NSError **
parameter, such a method should also have a non-void
return type and indicate success or failure via its return value. So, using your example, dataWithJSONObject:options:error:
will return nil
if it encounters an error and may return an error object via its third parameter.
Any method accepting an NSError **
parameter for error returns should accept either the address of an NSError *
variable or NULL
. The latter value means the user does not wish to have an error object returned. This means that the method accepting an NSError **
parameter must check the parameter value is not NULL
before attempting to assign an error object via it.
So your method handleData:error:
must be prepared to accept NULL
and needs to test for it. Your code therefore must include something similar to:
// Check if NSJSONSerialization had errors
if (jsonData == nil)
{
// Error occurred, did it return an error object?
if (error != NULL && *error != nil)
{
// we have an error object
}
else
{
// we have an error but no error object describing it
}
}
else
{
// no JSON error
}
HTH
Upvotes: 4