简体   繁体   中英

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.

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.

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];
    }];
}];

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.

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 (ie, 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM