objective-cvariables

Confused about the use of one or more asterisks in Objective-C


I'm reading a book on Core Data and at some point the author has this validation method:

- (BOOL)validateRadius:(id *)ioValue error:(NSError **)outError {
    NSLog(@"Validating radius using custom method");

    if ([*ioValue floatValue] < 7.0 || [*ioValue floatValue] > 10.0) { 
        // Fill out the error object 
        if (outError != NULL) {
            NSString *msg = @"Radius must be between 7.0 and 10.0";
            NSDictionary *dict = [NSDictionary dictionaryWithObject:msg forKey:NSLocalizedDescriptionKey];
            NSError *error = [[[NSError alloc] initWithDomain:@"Shapes" code:10 userInfo: dict] autorelease];
            *outError = error;
        }
        return NO;
    }
    return YES;
}

There are two things that confuse me and since I don't even know what they are technically called, can't seem to find in Google.

First one is the use of double asterisks ** in the method signature:

- (BOOL)validateRadius:(id *)ioValue error:(NSError **)outError {

The second is the use of a single asterisks * when on the reciever of a method call:

[*ioValue floatValue]

I haven't seen any of these two things before so I'm wondering what they are about. Just started iOS programming 6 or so months ago.

Any explanations or pointers to online documentation are very welcome.


Solution

  • (id *)ioValue means that ioValue is a pointer to an id, not an id itself. The expression *ioValue refers to the id that ioValue points to.

    (NSError **)outError means that outError is a pointer to an NSError * (which is, in turn, a pointer to an NSError).

    The usual reason for passing pointers to functions in this fashion is to allow the function to return something to the caller.

    In the above case, the function could assign a new id to the variable that the caller passed in: *ioValue = something(). However, since the above function doesn't actually do this, it seems redundant; it could have been written as (id)ioValue, and then referred to it as ioValue instead of *ioValue.

    The outError case makes perfect sense, however. In the event of an error, the function creates an error object (NSError *error = ...) and assigns it to the passed-in variable thus: *outError = error. This has the effect of changing the original variable that the caller passed in, so that when the function returns, the caller can inspect the variable to see the error that was produced:

    id ioValue = something();
    IOError *err;
    if ([foo validateRadius:&ioValue error:&err]) {
        NSLog("Yippee!");
    } else {
        reportError(err);
    }