Alan Quatermain

The Tumblog of one Jim Dovey, iOS Software Chief Architect at Kobo in Toronto, Ontario.
He Twitters, he has an , and can occasionally be found on LinkedIn or Facebook.
If you have a query, you can ask it here.

This blog contains personal opinions, and is not endorsed by any company.

206150588

A Blocks Gotcha

So I was just writing some code, and I refactored it a bit by putting a little chunk into a block, then calling that block in multiple places. Here’s the gist original declaration:

NSXMLDocument * (^fetcher)(NSString *) = ^(NSString * typeName) {
    NSArray * arguments = [NSArray arrayWithObjects: ...];

    // fetch the data
    NSXMLDocument * doc = ...;
    if ( doc == nil )
    {
        LogError( ... );
        return ( nil );
    }

    dispatch_async( dispatch_get_main_queue(), ^{
        [progress setDoubleValue: [progress doubleValue] + step];
    });

    return ( doc );
};

Attempting to compile this, however, resulted in the following error from Clang:

error: incompatible block pointer types initializing 'void *(^)(NSString *)', expected
'NSXMLDocument *(^)(NSString *)'
     NSXMLDocument * (^fetcher)(NSString *) = ^(NSString * typeName) {
                                              ^~~~~~~~~~~~~~~~~~~~~~~~

I scratched my head for a while over this, but it all came down to this line:

return ( nil );

It transpires that since MacTypes.h (used by Security in this case) #defines nil as a synonym for NULL, the preprocessor turns that into:

return ( (void *)0 );

Since that’s the first return statement in the block, the compiler creates a block with a void * return type. DOH. The solution was to type-cast the result:

return ( (NSXMLDocument *) nil );

It’s not the most elegant, and it would be nice if MacTypes.h didn’t stomp all over ObjC’s nil data type, but at least it works.

3 notes

  1. quatermain posted this