Typedef block causes errors


#1

Page 233, typedef section states:

[quote]
Instead of declaring devowelizer this way void (^devowelizer)(id, NSUInteger, BOOL *); you can replace that line with the following declaration: ArrayEnumerationBlock devowelizer;[/quote]

I did that only to be see the following two errors on these lines that I tried to figure out…

typedef void (^ArrayEnumerationBlock) (id, NSUInteger, BOOL);

int main (int argc, const char * argv[])
{

@autoreleasepool {
    
 // Create the array of strings to devowelize and a container for new ones
    NSArray *oldStrings = [NSArray arrayWithObjects:
                           @"Sauerkraut", @"raygun", @"Big Nerd Ranch", @"Mississippi", nil];
    NSLog(@"old strings: %@", oldStrings);
    NSMutableArray *newStrings = [NSMutableArray array];
    
    // Create a list of characters that we'll remove from the string
    NSArray *vowels = [NSArray arrayWithObjects:@"a", @"e", @"i", @"o", @"u", nil];
    
    // Declare the block variable
    ArrayEnumerationBlock devowelizer;
    
    // Assign a block to the variable
    // devowelizer = ^(id string, NSUInteger i, BOOL *stop) {
    devowelizer = ^(id string, NSUInteger i, BOOL *stop) {

[color=#FF0000]Incompatible block pointer types assigning to ‘__strong ArrayEnumerationBlock’ (aka ‘void (^__strong)(__strong id, NSUInteger, BOOL)’) from ‘void (^)(__strong id, NSUInteger, BOOL *)’[/color]
NSRange yRange = [string rangeOfString:@"y"
options:NSCaseInsensitiveSearch];
// Did I find a y"
if (yRange.location != NSNotFound) {
*stop = YES; // Prevent further iterations
return; // Stop this iteration
}

        NSMutableString *newString = [NSMutableString stringWithString:string];
        
        // Iterate over the array of vowels, replacing occurrences of each
        // with an empty string.
        
        for (NSString *s in vowels){
             NSRange fullRange = NSMakeRange(0, [newString length]);
            [newString replaceOccurrencesOfString:s 
                                       withString:@"" 
                                          options:NSCaseInsensitiveSearch 
                                            range:fullRange];
            }
        
        [newStrings addObject:newString];
    
    }; // End block assingnment
    
    // Iterate over the array with our block
    [oldStrings enumerateObjectsUsingBlock:devowelizer];

[color=#FF0000] Incompatible block pointer types assigning to ‘__strong ArrayEnumerationBlock’ (aka ‘void (^__strong)(__strong id, NSUInteger, BOOL)’) from ‘void (^)(__strong id, NSUInteger, BOOL *)’[/color]
NSLog(@“New strings: %@”, newStrings);

}
return 0;

}


#2

For anyone else coming across this posting - the error is forgetting the * in the BOOL parameter:

typedef void (^ArrayEnumerationBlock) (id, NSUInteger, BOOL);

hould be

typedef void (^ArrayEnumerationBlock) (id, NSUInteger, BOOL*);


#3

Thank you so much. That was it.


#4

Sorry if I’m missing something obvious from a prior chapter, but why is BOOL the only parameter that needs an asterisk?


#5

It is pass-by-reference. From the block you can pass back “YES, please keep going.” or “NO, forget it, I’ve done what I need to do. No need to continue iterating through the rest of the items in the array.”


#6

Thanks, Aaron. Makes sense.

And thanks again for your commitment to this message board!