Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ios store ^block in dictionary or array?

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?

like image 938
hzxu Avatar asked Oct 24 '12 04:10

hzxu


2 Answers

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]
like image 77
Mr Bonjour Avatar answered Oct 14 '22 08:10

Mr Bonjour


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.

like image 36
newacct Avatar answered Oct 14 '22 09:10

newacct