[iOS] Pointer to Block Pointer

iOS block programming feature is pretty cool, it makes asynchronous programming easier. This time I want to talk about block pointer. A block pointer is a type of variable that we can use to refer to a block, for example

void (^blockPointer)(void) = void ^(void) { NSLog(@"inside a block"); };

We can then execute the block like normal function call.

blockPointer();

What’s interesting is that a block pointer is actually an Objective-C object. We can do copy, retain, release, autorelease (more on this can be read here) on it, and also assign a pointer to it :D.

I’ll show you a sample use case where I want to make a pointer to a block pointer. Suppose I have a function that does something asynchronously and executes a block at the end of it.

- (void) asyncFunction:(void (^)(void)) block {
  // do something asynchronously, then execute the block at the end
  block();
}

Then I have another function, a nasty one with many nested ifs, that passes a block to asyncFunction depending on the conditions. When it doesn’t call asyncFunction, the block still has to be executed. So the block must be called exactly once, no matter which conditional route it takes.

Solution A: do some brute force with myriads of if-else

- (void)nastyFunction:(void (^)(void)) block {
  if (...) {
    if (...) {
      [self asyncFunction:block];
    } else {
      /* myriads of other if-else */
    }
  } else (...) {
    block();
  }
}

Solution B: Because a block pointer is an Objective-C object, we can assign nil to it. So after calling asyncFunction, we assign the block to nil. At the end of nastyFunction we execute the block only if it’s not nil.

- (void)nastyFunction:(void (^)(void)) block {
  if (...) {
    if (...) {
      [self asyncFunction:block];
      block = nil;
    }
    /* myriads of other ifs */
  }
  if (block != nil){
    block();
  }
}

The number of else decreases, the number of ‘block = nil‘ increases.

Solution C: this is where pointer to block pointer becomes useful. Instead of writing ‘block=nil‘ numerous times, we write it only once inside asyncFunction. But to change the value of block inside nastyFunction, we have to pass it to asyncFunction using a pointer. We declare a pointer to block pointer using this statement.

void (^pointerToBlockPointer *)(void)

So asyncFunction becomes

- (void) asyncFunction:(void (^*)(void)) block {
  // do something asynchronously, then execute the block at the end and assign it to nil
  *block();
  *block = nil;
}

And we pass the block from nastyFunction using its address.

- (void)nastyFunction:(void (^)(void)) block {
  if (...) {
    if (...) {
      [self asyncFunction:&block];  
    }
    /* myriads of other ifs */
  }
  if (block != nil){
    block();
  }
}

The declaration for pointer to block pointer is pretty funny, I got it from XCode compilation error message :D.

Another useful tips: if you want to simplify the declaration, you can typedef the block pointer.

typedef (void)(^BlockPointerType)(void);

So the pointer to it can be written as

BlockPointerType * pointerToBlockPointer;
Advertisements
This entry was posted in Programming and tagged , , , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s