mikeash.com: just this guy, you know?

Posted at 2009-08-14 20:06 | RSS feed (Full text feed) | Blog Index
Next article: Friday Q&A 2009-08-21: Writing Vararg Macros and Functions
Previous article: Friday Q&A 2009-07-17: Format Strings Tips and Tricks
Tags: blocks fridayqna
Friday Q&A 2009-08-14: Practical Blocks
by Mike Ash  

Welcome back to another edition of Friday Q&A. I'm back from my break and ready to bring you more programming goodies. This week I want to take Landon Fuller's suggestion to write a followup to my original Friday Q&A on blocks now that the design is finalized and code available for them.

Although Apple has yet to ship blocks with any of their developer tools, they have released code for their blocks implementation due to their participation in the open-source compilers gcc and clang. Landon has used this code to put together PLBlocks, which allows building and running blocks-based code on Mac OS X 10.5. While there are no blocks-based APIs on 10.5 (aside from the very basics which are part of the runtime), they can still be used to great effect.

I'm not going to cover the installation or basic use of PLBlocks here, as the PLBlocks page covers this in great detail. If you want to follow along, go there and follow the directions. For more information about how blocks work, see Clang's blocks language spec and implementation spec.

I'm also going to assume that you know the basics of block syntax and usage, as covered in my last Friday Q&A on the subject. Today's is essentially Part II of that one. If you haven't already, go read that one first.

Fundamentals
Blocks are Objective-C objects. When you write a block in code, that is an expression of object type, much like the @"..." constant string syntax gives you an expression of object type. You can then use this object like you would any other Objective-C object, by sending it messages that it responds to, putting it into containers, passing it as a parameter, returning it, etc.

There is a major difference from the constant string syntax. Unlike constant strings, blocks are not exactly the same each time through a piece of code. This is because blocks capture their enclosing scope, and that scope is different every time they're called. In short, each time code execution hits a ^{...} construct, a new object is created.

Allocating a new object every time would be kind of slow, so blocks take an unusual approach: the object you get from a ^{...} construct is a stack object. This means that it has the same lifetime as local variables, and will be destroyed automatically upon leaving the current scope. Weird, huh?

It's frequently useful for a block to outlive the scope where it was created. For example, you may want to return a block, or save it for later. For this to work, you must copy the block. You can do this like any other Objective-C object by sending it the -copy message. And like any other Objective-C object, if you aren't running under Garbage Collection then you own the resulting object and must eventually dispose of it using -release or -autorelease.

This, then, is an example of returning a block from a method:

    - (void (^)(void))block { return [[^{ ... } copy] autorelease]; }

Note that external variable capture gives const copies of those variables by default. In other words, this is not legal:

    int i;
    ^{ i++; };
The way to work around this is to use the __block keyword, like so:
    __block int i;
    ^{ i++; };
The reason for requiring explicit marking of local variables like this is because __block variables are significantly more costly than the regular kind, and have different semantics when applied to Objective-C object pointers (more details on that later), so rather than figure out a one-size-fits-all policy, the blocks guys decided it was better to just let the programmer choose.

Examples
I'm going to be showing a bunch of examples for how to use blocks with PLBlocks on 10.5. Those of you who want to follow along may wish to look at the example project I built, which you can get out of my public subversion repository here:

    svn co http://www.mikeash.com/svn/PLBlocksPlayground/
If you just want to browse the code you can just click on the link in that command.

Custom APIs
That's the basic idea of how they work, now let's see what we can do with them.

As I mentioned in my first blocks post, blocks essentially allow you to build new control constructs without needing to modify the language. Before we get into it, I want to introduce a little typedef to keep things simple. Most control-construct blocks are blocks which take no parameters and return no value. As such, it's nice to have that type wrapped up in something a little nicer to write:

    typedef void (^BasicBlock)(void);
As a really simple example, let's take a fairly common task in Cocoa: that of running some code with an inner autorelease pool to keep your high water mark low. Normally this would look like:
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    ...
    [pool release];
This is not all that bad, but it's a little verbose. We could write a macro to do this, but macros are fairly evil, and often have hidden gotchas. Instead, let's write a little function to do this, using blocks:
    void WithAutoreleasePool(BasicBlock block)
    {
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        block();
        [pool release];
    }
And then we can use it like so:
    for(id obj in array)
        WithAutoreleasePool(^{
            [self createLotsOfTemporaryObjectsWith:obj];
        });
That's quicker and easier than writing it out manually, and just as readable at the end. Nice!

Let's attack something a little more complicated. It's common in Cocoa programs to need to run some code after a short delay, using -performSelector:withObject:afterDelay:. Often we'll use a zero delay to mean "run this code immediately after returning to the runloop". The trouble with this is that it requires an object and a separate method, and getting the relevant context over can be painful. Let's write a quickie blocks function instead:

    void RunAfterDelay(NSTimeInterval delay, BasicBlock block)
    {
        [[[block copy] autorelease] performSelector: @selector(my_callBlock) withObject: nil afterDelay: delay];
    }
Notice how we have to do a copy/autorelease on the block so that the object stays alive until the perform is complete. This makes use of a small category on NSObject to actually invoke the block, taking advantage of the fact that blocks are NSObjects too:
    @implementation NSObject (BlocksAdditions)
    
    - (void)my_callBlock
    {
        void (^block)(void) = (id)self;
        block();
    }
    
    @end
Then we can use it like so:
    NSString *something = ...;
    RunAfterDelay(0, ^{
        NSLog(@"%@", something);
        [self doWorkWithSomething: something];
    });
This is a lot easier to work with than the typical Cocoa pattern for anything more complex.

Another thing that we frequently write is a critical section of code protected by a lock. Normally this would look like:

    [lock lock];
    ...do stuff...
    [lock unlock];
However this can be somewhat error prone. For example if you forget to unlock the lock in one code path, or return from the middle, or throw an exception, then your application will deadlock. The safest way to write the above is to use a @try/@finally block like so:
    [lock lock];
    @try
    {
        ...do stuff...
    }
    @finally
    {
        [lock unlock];
    }
Which is sort of cumbersome. We can turn this idiom into a blocks-based method on NSLock to handle locking and unlocking completely automatically:
    @implementation NSLock (BlocksAdditions)
    
    - (void)whileLocked: (BasicBlock)block
    {
        [self lock];
        @try
        {
            block();
        }
        @finally
        {
            [self unlock];
        }
    }
    
    @end
This isn't exactly the same. For example, with the explicit @try/@finally you can return a value from the method from within the @try block and it works, whereas doing this from inside the block will simply error, because you'll be returning a value from the block instead, which will make the block's type incompatible. This can be worked around by using a __block qualified variable to hold the return value. In my opinion this is superior, as it helps discourage tricky behavior inside the critical section, where the potential for bugs is high.

A Stylistic Note
There are two interesting choices in the above code, both due to the same reason. The first choice is that these are functions, not methods. Since blocks are NSObjects, category methods on NSObjects can be used for them. Rather than a RunAfterDelay function, we could write a -runAfterDelay: method on NSObject. The second choice is to always put the block parameter last, even though it's the most significant parameter and would make more sense to go first.

The reason for both of these is that you want the block to come absolutely last so that your code remains readable when the block is split onto multiple lines. For example, imagine some nested blocks code using the above functions recast using methods instead:

    [^{
        for(id obj in array)
            [^{
                [self doImportantWork:obj];
            } withAutoreleasePool];
    } runAfterDelay: 0];
This is significantly less readable. The code appears first, and what's being done with it only comes at the end, which can come much later. When nested, you have to read everything in LIFO order. For this reason, it's a bad idea to write control constructs using methods, and when taking a block as a parameter, always put the block last.

Collections
Using blocks with collections can make for powerful looping constructs. Let's start out with this really simple substitute for a for loop, as a method on NSArray:

    - (void)do: (void (^)(id obj))block
    {
        for(id obj in self)
            block(obj);
    }
This is not really all that interesting. It ends up being just like a for/in loop, but without the ability to statically type the objects. (It would have been nice to have before Apple introduced for/in, at least, illustrating the idea of adding your own control constructs using blocks.) Example use:
    NSArray *array = ...;
    [array do: ^(id obj){ NSLog(@"%@", obj); }];
Not too exciting. Here's one that's more interesting. This uses a block to map one array to a new array:
    - (NSArray *)map: (id (^)(id obj))block
    {
        NSMutableArray *new = [NSMutableArray array];
        for(id obj in self)
        {
            id newObj = block(obj);
            [new addObject: newObj ? newObj : [NSNull null]];
        }
        return new;
    }
This shows how you could use it to construct an array of name strings from an array of people:
    NSArray *people = ...;
    NSArray *names = [people map: ^(id person){
        return [NSString stringWithFormat: @"%@ %@", [person firstName], [person lastName]];
    }];
This is much nicer than manually writing the loop encapsulated in the -map: method. By passing blocks around, we only have to write that loop once, then reuse it many times.

One more example, this allows filtering an array:

    - (NSArray *)select: (BOOL (^)(id obj))block
    {
        NSMutableArray *new = [NSMutableArray array];
        for(id obj in self)
            if(block(obj))
                [new addObject: obj];
        return new;
    }
An example of using it to filter out strings that are too short:
    NSArray *longStrings = [strings select: ^ BOOL (id obj) { return [obj length] > 5; }];
Note the explicit return value. The result from C comparison operators is int, not BOOL, so allowing the compiler to infer the return value would produce a block of incompatible type. An alternative would be to cast the expression used in the return statement.

Here's an example of a use in a GUI application, for getting all the text fields inside a particular view:

    NSArray *textFields = [[view subviews] select: ^(id obj){ return [obj isKindOfClass: [NSTextField class]]; }];

Callbacks
Callbacks-based APIs are a place where blocks really shine. Instead of passing a selector/delegate pair, or a function pointer/context pointer pair, pass a block. It makes it much easier to pass context around (since the block packages up all needed context automatically) and keeps all of the code nearby.

An obvious example of a callback is notifications. While there's often a benefit to having separated methods for notifications, the implementation is easy and it can sometimes make for nicer code:

    @implementation NSNotificationCenter (BlocksAdditions)
    
    - (void)addObserverForName: (NSString *)name object: (id)object block: (void (^)(NSNotification *note))block
    {
        [self addObserver: [block copy] selector: @selector(my_callBlockWithObject:) name: name object: object];
    }
    
    @end
The my_callBlockWithObject: method is implemented in a category on NSObject, much like the my_callBlock method seen earlier, except that it takes a parameter and passes that parameter on to the block.

You can use it like so:

    [[NSNotificationCenter defaultCenter] addObserverForName: NSApplicationDidBecomeActiveNotification
                                                      object: nil
                                                       block: ^(NSNotification *note){ NSLog(@"Did become active"); }];
Note that there is no mechanism provided for deactivating the notification block. This could be added, but would require additional state to be managed by the caller. Such a mechanism is left as an exercise for the reader.

Sheets are a good example of a painful callbacks-based API in Cocoa. You have to implement a callback method, then cram all of the state associated with the sheet, which is often large, either into the single void * context parameter provided, or into instance variables. Neither way is particularly nice.

Here is a small category which translates this API to use blocks instead:

    @implementation NSApplication (SheetAdditions)
    
    - (void)beginSheet: (NSWindow *)sheet modalForWindow:(NSWindow *)docWindow didEndBlock: (void (^)(NSInteger returnCode))block
    {
        [self beginSheet: sheet
          modalForWindow: docWindow
           modalDelegate: self
          didEndSelector: @selector(my_blockSheetDidEnd:returnCode:contextInfo:)
             contextInfo: [block copy]];
    }
    
    - (void)my_blockSheetDidEnd: (NSWindow *)sheet returnCode: (NSInteger)returnCode contextInfo: (void *)contextInfo
    {
        void (^block)(NSInteger returnCode) = contextInfo;
        block(returnCode);
        [block release];
    }
    
    @end
Now you can simply provide a block inline, right in with the rest of your code, and access all of the necessary context directly.

Another example of a similarly painful API is NSURLConnection. It provides two modes: synchronous and asynchronous. The synchronous mode can only be used from a secondary thread which can be blocked for arbitrarily long amounts of time, since any network operation can take a long time to complete. The asynchronous mode requires writing a lot of boilerplate code. Let's write a method that adds an asynchronous mode that simply makes a single call to a block when it's done to hand over the data, the response metadata, and the error, if any. To do this, we'll just use the synchronous API in a background thread. This code uses two functions, RunInBackground and RunOnThread, which are blocks-based APIs for spawning a new thread and running a block on an existing thread, respectively. These functions are pretty straightforward to implement and I won't duplicate them here, but you can get them in the sample project if you need.

Here's what the code looks like:

    @implementation NSURLConnection (BlocksAdditions)
    
    + (void)sendAsynchronousRequest: (NSURLRequest *)request
                    completionBlock: (void (^)(NSData *data, NSURLResponse *response, NSError *error))block
    {
        NSThread *originalThread = [NSThread currentThread];
        
        RunInBackground(^{
            WithAutoreleasePool(^{
                NSURLResponse *response = nil;
                NSError *error = nil;
                NSData *data = [self sendSynchronousRequest: request returningResponse: &response error: &error;];
                RunOnThread(originalThread, NO, ^{ block(data, response, error); });
            });
        });
    }
    
    @end
There are a couple of notable features here. First, notice how the current thread is saved into a local variable, then later on accessed inside a block which will be executed on a different thread. This shows how blocks can be used to easily pass context around in callbacks. Notice then how the block passed to RunInBackground ends with a call to RunOnThread which uses another block to call back to the originating thread. This kind of nested block messaging is handy for making asynchronous callbacks in a concise manner.

Here's an example of using this API:

    NSURLRequest *request = [NSURLRequest requestWithURL: [NSURL URLWithString: @"http://www.google.com/"]];
    [NSURLConnection sendAsynchronousRequest: request
                             completionBlock: ^(NSData *data, NSURLResponse *response, NSError *error){
        NSLog(@"data: %ld bytes  response: %@  error: %@", (long)[data length], response, error);
    }];
This is very nice! The equivalent using the asynchronous APIs would require implementing several methods, and possibly a whole new class. Using the synchronous API explicitly, and doing all the work of managing the secondary thread, and calling back to the main thread when done, passing along all of the objects that were received, would require many more lines of code than this does.

Caveats
It should be no surprise that there are some things to look out for when working with blocks.

When blocks are copied, any local object variables they refer to get automatically retained. They are then automatically released when the block is destroyed. This is convenient to ensure that the references remain valid. Any reference to self is a reference to a local object variable, causing self to be retained. Any reference to an instance variable is an implicit reference to self and causes the same thing. However, this makes it easy to cause a retain cycle in some instances. Imagine using a more fleshed-out version of that blocks-based notification API which allows unregistering the notification. If your block refers to self in any way, and you do the standard Cocoa thing of unregistering the notification in -dealloc, your object will leak because the block will hold a reference to your object.

A simple workaround to this lies in the fact that __block variables are not retained. This is because such variables are mutable, and automatic memory management of them would require each mutation to generate memory management code behind the scenes. This was seen as too intrusive and difficult to get right, especially since the same block may be executing from multiple threads simultaneously. Thus you can avoid the retain cycle like so:

    __block MyClass *blockSelf = self;
    ^{
        [blockSelf message];
        [blockSelf->ivar message];
    };
CoreFoundation types need to be retain/released when captured in non-__block variables, just like Objective-C objects, since they really are Objective-C objects as well. However, the compiler doesn't see them this way. To help with this, the compilers have added an attribute, __attribute__((NSObject)), which causes struct pointers to be treated like Objective-C objects as far as their block retain/release semantics. We can assume that Apple will be applying this attribute to all CFTypes on 10.6. While we're stuck in 10.5, however, they won't have this attribute, and so CoreFoundation objects will not be correctly memory managed when captured by blocks. To avoid problems, either avoid capturing CoreFoundation objects in blocks (declaring the variables to be of the equivalent Objective-C toll-free bridged type instead will convince the compiler to retain/release them) or ensure that the lifetime of the CF objects is at least as long as the lifetime of the block.

Another pitfall with blocks is due to the fact that they are stack objects. Using the ^{...} syntax is essentially the same, behind the scenes, as declaring a local variable and then taking its address for something. The address can be passed around, but as soon as you leave the scope in which the local variable was declared, it's no longer valid. Thus, something as innocent as this ends up being broken code:

    BasicBlock block;
    if(condition)
        block = ^{...};
    else
        block = ^{...};
The body of the if statement (and the else clause) is a separate scope from the main body which is destroyed as soon as control flow exits the if/else clause. The block reference which is being stored in block is invalid as soon as control flow returns to the main body! It's simple to fix this just by copying the blocks:
    BasicBlock block;
    if(condition)
        block = [[^{...} copy] autorelease];
    else
        block = [[^{...} copy] autorelease];
The main danger with this isn't that it's hard to fix (it's not) but that it's not necessarily easy to notice when you do it.

Conclusion
That wraps up this week's Friday Q&A. You've seen how to get blocks up and running with your current tool chain, a few examples of how they can be used in a useful manner, and some problems to watch out for. Now you're ready to start using blocks in your 10.5 apps today, no need to wait for 10.6 to ship.

Questions about blocks? Have your own ideas for how best to use them? Post below.

Come back next week for another edition of Friday Q&A. As always, Friday Q&A is driven by your ideas. If you have a topic that you would like to see covered here, post it below or e-mail it to me.

Did you enjoy this article? I'm selling whole books full of them! Volumes II and III are now out! They're available as ePub, PDF, print, and on iBooks and Kindle. Click here for more information.

Comments:

NSLog(@"isFirst: %s", ([self isFirst] ? "YES" : "NO"));
isFirst YES
Great article !!

Though in iterations you forgot two things:
1. Why not include as parameter the index of object in the array ? That'd be quite useful, also we can't break out of the loop in the middle from the block... A BOOL *stop parameter would be nice. :P

2. You didn't show NSDictionary iterations where you can get ass parameter of the block both keys and values at the same time, and avoid writing [dict objectForKey: key] all the time.


Anyway, it's very nice, thanks.
My emphasis in the array iteration example was on simplicity. Since the major advantage is syntactic niceness, you want the code to be as simple as possible. Adding mandatory parameters that have to be typed out for every usage makes it much less simple. My preference would be to include the more complicated versions as an alternate API but always make sure the simple, one-parameter variant is available.
As always, a very good and revealing read. Thank you!
Great article this week, thanks!

I'm impressed by how much this one feature increases the expressiveness of the language. With this, who needs Ruby anymore? ;)
Very nice article :) Thought I had a good grasp of blocks by now but I was as always proven wrong! Cool block usages too.

I'm writing a guide on C blocks. I added some references to this blog entry in it. It's over at: http://thirdcog.eu/pwcblocks/
Hey Mike, great post so far! Was just at the beginning of it and noticed you mentioned the 0.0 delay trick.

It reminded me that I wrote a blog post on this about a week ago or so, solving it in the old Leopard-y way (ie, without blocks)... http://www.degutis.org/dev/2009/08/01/next-runloop-trick/ if anyone is interested!
Mike:

It seems worth noting to me that, unlike ObjC objects, you cannot execute a block that == nil. Otherwise you will crash, no question about it. Simplest way around this is to check it with a simple if() before executing, such as:


if (block)
    block();


That is all.
It's not "unlike ObjC objects". As I stated, blocks are ObjC objects. You can message nil blocks just like any other nil object. You can't call one using the special block calling syntax, but that's not exactly a big shock, since it's a completely different operation.

As for the if check, if you need to be told to use an if statement to avoid calling a nil block, then you are on the wrong blog.
My apologies, then, Mike. Feel free to remove my ignorant, redundant, and just downright dumb comment above.
Thanks for another awesome post!

Can't wait for blocks but in the meantime I have been using the NSProxy forwardInvocation pattern to capture a method call into an NSInvocation and then use perform selector, with delay, on thread, etc on the invocation instance.

Dave Dribin wrote about it at http://toxicsoftware.com/grab-that-invocation/ way back when and I've been using a customized version which I posted about at: http://rel.me/2009/05/22/nsinvocation-nsproxy-forwardinvocatio/

For example:
[[self gh_proxyAfterDelay:0] listWithOffset:40 limit:20];

Anyway, thought it might be useful to share this technique since you have the RunAfterDelay example above. Not sure if its really that related to the blocks proposal..

Looking forward to the next one.
Maybe you're working under some other constraints, but a major point of this post is that you don't have to wait for blocks. Thanks to PLBlocks, you can have them right now. They work fine on Leopard.
So with PLBlocks you get them now with Leopard, with no need to change from the default compiler and all?

But with 10.6 it seems that we'll be getting new developer tools, whereby we would not need to use PLBlocks? I guess I'm a little unclear here (maybe I'm also reading the wrong blog).

(Would we be able to run part of the new dev tools (including the blocks bits) on 10.5.9 or whatever? Or would we forever be restricted to PLBlocks based implementations when not on Snow Leopard? (Since currently unemployed I'm trying to make my PowerMac dual G5 last as long as possible.)

Thanks for all the thought provoking examples. When I look at blocks they seem easy way to roll up context when defining variable (per object, rather than class defined) behavior. In those cases distinguishing invocation via function call or methods doesn't seem to be critical, yes?
There's a fairly significant gulf between "how to use an if statement" and "how does all of this blocks stuff work right now?" I'd call this the right place for the latter.

The basic situation appears to be public, and not covered by NDA, via Apple's into to Grand Central Dispatch here: http://images.apple.com/macosx/technology/docs/GrandCentral_TB_brief_20090608.pdf

Apple's blocks implementation is currently limited to open source release in gcc and Clang. This is what PLBlocks is built from. It will make an appearance in Snow Leopard. Traditionally, Apple does not make major language/API changes in the middle of an OS life cycle, so we can say pretty confidently that blocks support will not be showing up in the 10.5.x series.

On 10.5, your sole choice (unless you want to build your own) for blocks is PLBlocks. PLBlocks requires installing and using a custom compiler for blocks-using code, however this is extremely easy to do. It also requires shipping a framework which contains the blocks runtime code; this is also very easy. PLBlocks is built in such a way that blocks-using code built on 10.5 using PLBlocks will continue to work fine on 10.6 and will not conflict with the built-in blocks system.

On 10.6, you have two choices. First, you can use the Apple-standard compilers to build code with blocks. This code will require 10.6 to run, because it will require Apple's blocks runtime. It might be possible to backport this runtime to 10.5, but I doubt that anyone will. Symbol conflicts will make life unpleasant. The PLBlocks approach of using different symbol names to ensure no conflicts can happen seems like the superior way.

The other choice is to use PLBlocks even on 10.6, which will generate 10.5-compatible code. Just like on 10.5, you'll be installing and building with a custom compiler and will be shipping the PLBlocks framework.

If you're on a G5 then your only choice is to use PLBlocks, since 10.6 won't be available. However there's no real disadvantage to PLBlocks; the semantics and functionality are identical to what Apple will give us. This only makes sense, as PLBlocks is built with apple's code! The main advantage on 10.6 is the presence of lots of tasty APIs that use blocks, like Grand Central Dispatch, which you can't use on 10.5. But as far as blocks themselves go, there's nothing wrong with using PLBlocks to get them.

As for function call/method invocation, the only point I was making was that there's no reason to expect the block call syntax to tolerate a nil block just because the [] message send syntax does. It's an unrelated operation with unrelated semantics.
Blocks are Objective C objects only in the presence of the Objective C runtime. Otherwise they are just plain data structures. And as an interesting side note, blocks introduce another root object; blocks don't inherit from NSObject or NSProxy.
August, according to http://clang.llvm.org/docs/BlockLanguageSpec.txt:
"All Blocks are constructed to be Objective-C objects regardless of whether the Objective-C runtime is operational in the program or not"

Even if there is no ObjC runtime, the structs representing blocks will be objective-c objects; if you write a C or C++ library that uses blocks, you can link that library to an ObjC application, and any blocks that are returned will be Objective-C objects.

Also, if blocks don't inherit from NSObject, how come performSelector:withObject:afterDelay: works with blocks, as per Mike's examples above?
I can't speak about Apple's blocks, but PLBlocks certainly are NSObjects:

@interface _PLAbstractBlock : NSObject

I can see no reason for them not to inherit from NSObject, and many reasons for them to.
"As for the if check, if you need to be told to use an if statement to avoid calling a nil block, then you are on the wrong blog."

Really? Anyone thinking if blocks are needed in there code for code they've written, shouldn't be writing code. They may or may-not be needed in library code, by they should never be needed otherwise.

Wow.
Do you think you could try reposting that comment in a manner which makes some form of sense? As it stands right now, it bears a strong resemblance to English but is in fact completely incomprehensible.
I have no idea what Some Reader is trying to say...

Anyway, I might be at the wrong blog too, as I am an objective-c noob, and a lot of the material on this blog goes WAY above my head. Still an interesting read, and hopefully once I get a better grasp of objective-c and cocoa, it will click into place :)

Keep up the good work!
I don't mean to sound like a snob, and if you're going for advanced topics even when you aren't quite there yet, then more power to you! It's just that the use of an if statement is so basic, as in first-week-of-introduction-to-programming basic, that it really does go beyond the limits. If you need to be told how to use an if statement then you need to learn basic programming before anything here will make any sense. But I'm sure you and everyone else here is at least beyond that first step.
I'm another programmer in water slightly over my head, so this post is greatly helpful as the technology of callable blocks is quite useful. An interesting question whether to use PLBlocks and get this functionality on Leopard and iPhone, but be off the LLVM track of SL and beyond. As for the comment regarding the notorious if statement, I suspect Mike was referring to the inclusion of the sample code, and not objecting to someone calling out a caution that such may be needed.
If you check out the PLBlocks mailing list, there is some discussion about how to use PLBlocks on 10.5 and have your code use the system blocks runtime when run on 10.6 and up. I don't think they've arrived at a consensus yet but you're not the only one thinking about it.

If you're not worried about using the 10.6 runtime but just thinking about being able to take advantage of 10.6 advances, you can start out writing 10.5/iPhone code with PLBlocks now, then just move your code to the newer compilers and OSes when the time comes. PLBlock syntax is 100% identical to the official Apple syntax so your code will just keep right on working.

As for the if statement, you're exactly right. Cautioning that you'll crash if you call a nil block, it's not surprising but it's not 100% obvious either. Showing people how to use an if statement in C, that's kind of ridiculous in context.
Sorry for the newbie question but I don't understand what the my_callBlock category does, or how for that matter. Can someone elaborate?
There is no my_callBlock category. I assume you mean the my_callBlock method, which is within the BlocksAdditions category.

void (^block)(void) is the declaration syntax for a block variable. You should already be familiar with this syntax from the first blocks article.

= (id)self; assigns the value of 'self' to 'block'. The cast is because 'self' is of type NSObject* in this code. Remember that blocks are objects too, and NSObject descendants, so we're basically just telling the compiler some more type information about what's going on.

block(); just calls the block declared above, which is pointing to the same object as 'self'.

If that did not answer your question, I recommend being more specific.
Helpful hint (from http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/GarbageCollection/Articles/gcUsing.html#//apple_ref/doc/uid/TP40008006) for those using garbage collection and the sheet-block code:

...
- contextInfo:[block copy]];
+ contextInfo:CFRetain([block copy])];
...
- [block release];
+ CFRelease(contextInfo);

Since objC retain/release are short-circuited, you have to CFRetain/CFRelease the block to avoid blowing up.
Great articles. I've learned a ton from them.

Given the example of the NSURLConnection block category (which is pretty close to real world scenario) are there and performance issues to be concerned about when nesting, copying, calling block methods, etc as compared to the non-block ways? I have no idea what the compiler is doing behind the scenes and was very curious if blocks reduce performance.
I just noticed that my example code fails to copy the block passed in. Whoops!

In short, the extra costs incurred, if any, are extremely small and will be far outweighed by the actual work being done by NSURLConnection.

Invoking a block is cheap. Cheaper than sending a message. This part can be ignored.

There are basically two costs incurred by the block approach. First, you have to pay for copies of captured local variables, and for the extra indirection needed when accessing __block qualified local variables. Second, you have to pay for copying the block itself, which includes a memory allocation for the block, another one for __block variables if there are any, copying the captured locals across, and performing memory management on captured ObjC object pointer variables.

Nothing here is all that dire. Memory allocations are pretty cheap, extremely cheap when compared to the cost of performing an HTTP request. There isn't much data to copy, so they'll go very fast.

For completeness, you also have to consider the cost incurred by the normal approach. To get equivalent functionality with NSURLConnection, you'll generally have a delegate object for each connection, which means, guess what, allocating memory for a new instance of it, copying values into it, etc. This will end up being pretty similar to the cost of using a block. Both cases will be dwarfed by the NSURLConnection itself.
Great article!
Are there any open sourced collections of block based categories yet for UIKit? That would be super useful.

Thanks for the great article. One thing I would like to add to this, is the difference between, stack, heap and global blocks. It took me a while to find out why code I have written did not break, although I had forgotten to copy a block and the declaration of it had gone out of scope, and nothing broke.

Turns out, that the block I declared did not use any variables from it's scope. This way, a global block object is created (NSGlobalBlock). This type of block object is allocated in some kind of global memory, and copying and retaining this block is a no-op. Even more, releasing it is a no-op.

It took me hours to, ironically, break my code.

For more info on this, see http://cocoawithlove.com/2009/10/how-blocks-are-implemented-and.html
One thing I just noticed, when declaring a block, you can give it a parameter that is a block with an empty arguments list.

It may sound odd, but it's extremely useful when you want to create a block that only takes one argument, which is a block that only takes one argument, which is a block that only takes one argument, which is a block that (etc, etc ...)

Just I thought it might also be helpful to someone besides me.

(Disclaimer: I've only tried this with LLVM + clang)
There's another trick, related to recursively calling the block which the call is within.


dispatch_block_t blk = ^{
  if (some_mutable_condition)
    blk(); // loop
};
blk(); // start loop


The problem is this doesn't work. When called within the block, `blk` refers to the pointer it was declared as, before it was assigned. Once assigned, it has a garbage reference and will crash. And don't get to thinking this will fix it, because it doesn't solve the problem at all:


dispatch_block_t blk;
blk = ^{
  if (some_mutable_condition)
    blk(); // loop
};
blk(); // start loop


One solution is to pass the block in, such as `blk(blk)` which is really lame since it requires changing your API. A better solution is to declare the block as a pointer to the block, and assign to the dereferenced pointer. This way, you still have access to the same memory address within the block as outside it, since that never changes, and can easily get to the -- well, you get the idea, it's just a pointer, which is a perfect work-around in and of itself for this problem. So you can do this and it works just fine:


dispatch_block_t *blk;
*blk = ^{
  if (some_mutable_condition)
    (*blk)(); // loop
};
(*blk)(); // start loop


This can be very useful when you want to implement a loop whose iterations are asynchronously performed, and thus you can't use a traditional for-loop or while-loop.. (I used this in conjunction with NSEnumerator in particular).
(Uhh... you should probably ignore the fact that I forgot to allocate memory for the pointer in the last example.)
Great article (still!), thanks!

One question: you state that you've chosen to used functions instead of methods for the sake of readability.

"The first choice is that these are functions, not methods. Since blocks are NSObjects, category methods on NSObjects can be used for them. Rather than a RunAfterDelay function, we could write a -runAfterDelay: method on NSObject...."


However, I imagine there are many situations where you might want to execute a block by calling a method on it. For instance, if you defined a -performBlock method on NSObject, you could stuff block objects into NSUndoManager:

   [[undoManager prepareWithInvocationTarget:^{
        NSLog( @"hello world" );
    }] performBlock];


Have I missed anything, or would this be a worthwhile reason to use methods?
No, that's pretty reasonable. The syntax is mildly ugly, but it's not bad. Functions are better, but when they don't work, methods do fine.
BasicBlock block;
    if(condition)
        block = ^{...};
    else
        block = ^{...};


seem no error, i already test like below:

typedef void (^BasicBlock)(void);
BasicBlock block;
    if(condition)
        block = ^{...};
    else
        block = ^{...};
block();

can you explain it?

willonboyzhang$gmail.com
Using a block outside the scope where you created in is undefined behavior. In C, undefined behavior can be basically anything, up to and including the behavior you consider to be "working".

In short, you can't determine whether code like that is good or not by testing it. It may work for you but fail elsewhere.
Hello and congratulations for this article and the entire blog!

I’m wondering how to turn the RunAfterDelay example into ARC-code.

I just removed the autorelease call and the compiler doesn’t complain, the app runs smoothly.
But how can I be sure the block will be released by ARC at some point?
I read your article on ARC and the __bridge… casting annotations. Are they needed here?

I hope this is not a silly question!
Hi! Nice post.
right now (after update to iOS 7) I have been experimenting some issues with:

@implementation NSNotificationCenter (BlocksAdditions)

- (void)addObserverForName: (NSString *)name object: (id)object block: (void (^)(NSNotification *note))block
{
    [self addObserver: [block copy] selector: @selector(my_callBlockWithObject:) name: name object: object];
}

when i call:

[[NSNotificationCenter defaultCenter] addObserverForName: NSApplicationDidBecomeActiveNotification
                                                      object: nil
                                                       block: ^(NSNotification *note){ NSLog(@"Did become active"); }];
    
    


before iOS 7 it worked but right now is not working :(
do you have any idea why?

Regards.
RunAfterDelay under ARC is something like

[[aBlock copy] performSelector: @selector(my_callBlock) withObject: nil afterDelay: aDelay];

though I wonder why not just use dispatch_after as the guts?
David Dunham: As far as the article goes, that's easy: this article was written before GCD was released.
Thank you for your article!
Learned a lot of new things!
Thanks for sharing this article.

Comments RSS feed for this page

Add your thoughts, post a comment:

Spam and off-topic posts will be deleted without notice. Culprits may be publicly humiliated at my sole discretion.

Name:
The Answer to the Ultimate Question of Life, the Universe, and Everything?
Comment:
Formatting: <i> <b> <blockquote> <code>.
NOTE: Due to an increase in spam, URLs are forbidden! Please provide search terms or fragment your URLs so they don't look like URLs.
Code syntax highlighting thanks to Pygments.
Hosted at DigitalOcean.