12

Can I store ^block in a dictionary or an array?

I need to listen to a server notification which I need to provide a block to handle the notification, and in my project several view controllers all want to hear the notification, so I made a generic notification manager, which has its own block for handling server notification and it has an array of delegates, so in the manager's block:

- (^)(NSString *message){
    for (delegate in allDelegates)
    {
        delegate.handlerBlock(message);
    }
}

but can I store blocks in a collection?

2
  • 3
    Indeed you can. Blocks are objective c objects, just remember to copy them off of the stack first. Commented Oct 24, 2012 at 4:52
  • 1
    What do you mean by copy them off the stack? Commented Oct 24, 2012 at 6:21

3 Answers 3

12

You can store object into collection. But take care of the scope: Copy them when they will be kept out of a function scope. This is your case since you are storing them in a array.

[NSArray arrayWithObject: 
[[^{ NSLog(@"block 1"); } copy] autorelease],
[[^{ NSLog(@"block 2"); } copy] autorelease], nil]

On ARC, you still need to tell it you absolutely needs to copy your block. It should release the block when the array is freed.

  [NSArray arrayWithObject: 
    [^{ NSLog(@"block 1"); } copy],
    [^{ NSLog(@"block 2"); } copy], nil]
Sign up to request clarification or add additional context in comments.

2 Comments

But I am using ARC, so I cannot use autorelease?
hzxu, if you use ARC, then forget autorelease. I have updated my example.
5

Blocks are special in that they should be copied in most cases when other objects should be retained. As you must have read by now, this is because blocks start out on the stack (a "stack block"), and is only valid in the local scope where they were defined. Copying a stack block gives you a heap block, and that will have a dynamic lifetime like normal objects. Copying a heap bock will simply retain it, so it is always right to copy a block when you need to keep it around for longer.

Now, functions that take a block argument generally take responsibility for copying blocks as necessary. So you don't need to do anything special when passing a block to these functions. However, in this case you're passing your block to [NSArray arrayWithObject:], which takes a normal object argument. Since it doesn't take a block argument, it doesn't know to copy the argument, so it will just retain it. So when you pass a block to a method that takes a normal object argument, you need to copy it first.

1 Comment

Blocks are not "special", copy should be used in almost all cases instead of retain. For most objects where retain is the "right" thing to do, copy will in fact just retain and return self.
-1

You will find how to do this if you read the very good article here. And take particular note of the "copy them off the stack first" idiom mentioned there.

1 Comment

The link is dead

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.