hzxu
hzxu

Reputation: 5823

ObjectiveC: Passing method parameter to a block inside a block?

I have a method:

- (void)myMethod:(NSError *)error
{
    [[self.data allKeys] enumerateUsingBlock:^(id obj, NSUInteger idx, BOOL *stop){
        __block NSString *channelName = obj;
        NSArray *subArray = [self.data objectForKey:obj];
        [subArray enumerateUsingBlock:^(id obj, NSUInteger idx, BOOL *stop){
            Wrapper *wrapper = obj;
            [wrapper handleError:error forChannel:channelName];
        }];
    }];
}

1) Do I need to use different names for parameters obj, idx and stop for the inner block?

2) Do I need or not need to define channelName as __block?

3) Do I need to define a weak self outside all blocks and use it in blocks?

edit:

channelName is used by inner block, and is passed to the handler block.

Upvotes: 0

Views: 2277

Answers (4)

Darren
Darren

Reputation: 25619

Your blocks run synchronously and are not copied to the heap, so there's nothing extra you have to do. There's no special memory management to consider (i.e., no weak references required) and you don't need the __block qualifier (unless the inner block needs to modify an outer variable).

On other words, all you have here is a plain old nested for-loop. The memory management is no different than an actual for-loop.

Upvotes: 0

CodaFi
CodaFi

Reputation: 43330

Am I doing the right thing?

No, you are missing the block literal declarator (^) in front of both of the arguments lists. Yes.

Do I need to use different names for parameters obj, idx and stop for the inner block?

No. Those arguments are the arguments of the block, and accessible within it's scope.

Do I need or not need to define channelName as __block?

No. It is declared within the scope of the block, and modified only within that block, therefore it does not need a __block specifier. __block declares a variable outside the scope of the block as mutable in the context of the block.

Do I need to define a weak self outside all blocks and use it in blocks?

No, but it's a darn good idea. Blocks retain their scope.

Upvotes: 0

Paul.s
Paul.s

Reputation: 38728

Am I doing the right thing?
Does it do what you need it to do?

Do I need to use different names for parameters obj, idx and stop for the inner block?
Have you tried it? Does it work?

Do I need or not need to define channelName as __block?
Are you actually using this anywhere? If not why declare it all?

Do I need to define a weak self outside all blocks and use it in blocks?
Nope there is no retain cycle here


You could consider using block enumeration on the dictionary to clean this up slightly

[self.data enumerateKeysAndObjectsUsingBlock:^(id key, NSArray *subArray, BOOL *stop) {
    [subArray enumerateUsingBlock:^(id obj, NSUInteger idx, BOOL *stop){
        Wrapper *wrapper = obj;
        [wrapper handleError:error];
    }];
}];

Upvotes: 0

rmaddy
rmaddy

Reputation: 318774

You don't need to use different parameter names for the inner block unless the inner block needs access to the parameters of the outer block. In the inner block, the duplicate names simply hide the parameters of the outer block. Different names would eliminate the hiding if needed.

You only need to mark a variables with __block if the variable is to be modified in the block. For read-only access to the variable, __block isn't needed.

I'm not positive about the self part of the question. Typically you will see a warning in Xcode when you are using a variable that could cause a retain cycle. Unless you see the warning, you should be OK.

Upvotes: 2

Related Questions