简体   繁体   中英

Objective-c passing error parameter to inside method

Its a common pattern to add an error output parameter when writing Objective-c methods.
As far as I know this is how you create a method that return an error if something is wrong:

- (void)doSomethingWithObj:(id)obj error:(NSError *__autoreleasing *)error {
    BOOL success = NO;

    // do somthing...

    if (!success) {
        *error = [NSError errorWithDomain:@"the.domain" code:0 userInfo:nil];
    }
}  

Now there are times when you just want that error parameter to reflect an error occurred in some other method you use inside your method, lets say:

- (void)fetchObjectInContext:(NSManagedObjectContext *)context error:(NSError *__autoreleasing *)error {
    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"SomeObject"];

    NSArray *results = [context executeFetchRequest:request error:nil];
}  

So I thought ok, I'll just pass the error parameter to the inside method, like this:

- (void)fetchObjectInContext:(NSManagedObjectContext *)context error:(NSError *__autoreleasing *)error {
    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"SomeObject"];

    NSArray *results = [context executeFetchRequest:request error:error];
    if (error) {
        NSLog(@"error %@", error);
    }
}  

But this approach has two issues:
1. the if (error) check returns YES even if there is no error.
2. the log line generates this warning: Format specifies type 'id' but the argument has type 'NSError *__autoreleasing *'

So what am I doing wrong here?

There are a couple of things wrong. Firstly the NSError object should not be used to test for errors, instead use the method's return value. Therefore your first example method should return BOOL to indicate success:

- (BOOL)doSomethingWithObj:(id)obj error:(NSError *__autoreleasing *)error {
    BOOL success = NO;

    // do somthing...

    if (!success) {
        if (error) {    // Check it's been passed, and if so create the error object.
            *error = [NSError errorWithDomain:@"the.domain" code:0 userInfo:nil];
        }
    }

    return success;
}  

And test for results being nil , not error being non- nil :

- (void)fetchObjectInContext:(NSManagedObjectContext *)context error:(NSError *__autoreleasing *)error {
    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"SomeObject"];

    NSArray *results = [context executeFetchRequest:request error:error];
    if (!results) {
        if (error && *error)
            NSLog(@"error %@", [(*error) localizedDescription]); // Here is your 2. I think.
        else
            NSLog(@"Unknown error");
    }
}  

Secondly the error parameter is commonly optional (as seen in your code where you pass nil , which should be NULL actually). Therefore you need to test if it's been passed before dereferencing it (see code above).

However to answer your overall question, yes it's good to pass the error parameter along to subordinate method calls and is commonly used.

I have no idea about your 2. until you update your code... standing by. I think your 2. issue is because you need to use [error localizedDescription] with NSLog() .

You are passing address of error not actual error this means &error So you need to derefrence the error pointer. NSError *__autoreleasing * you are taking parameter as address of error .We generally do this because objective c can return only one value.But error need to be known from where we are calling the mehod so passing it as address of error will make change to error if there an error comes in calle function . So if any error comes in below line

NSArray *results = [context executeFetchRequest:request error:error];

than it is automatically know to calle function ie doSomethingWithObj

if (*error) {
    NSLog(@"error %@", (*error).description);
 }

Use

NSLog(@"error %@", (*error).description);

instead of

NSLog(@"error %@", (error).description);

you have to pass &error

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM