Block in block, with __weak self

block, ios, objective-c, xcode

Solution

In this case (below) use just strong `self`, because the block is copied just for those few seconds. And usually if you want the `self` to perform block, you want to it to stay alive until that time, so strong reference is perfectly okay.

[self performBlock:^{
    [self doSomething]; // strong is OK
} afterDelay:delay];

Block inside a block? In your case those two block are just delayed one-shot blocks, so the same as above, use strong. But there are differences between blocks. If you store the block for longer time, maybe for multiple invocations you should avoid retain-cycles.

Example:

self.callback = ^{
    [self doSomething]; // should use weakSelf
};

This may cause retain-cycle. In fact it depends on how the block is used. We see that the block is stored (copied) in property for later use. However, you can prevent the retain-cycles by nullifying block that will not be used any more. In this case:

self.callback(); //invoke
self.callback = nil; //release

When using ARC, you don't have to copy blocks yourself. There were bugs in early versions after blocks were added, but now the compiler under ARC knows when to copy blocks. It is clever enough to copy it in this case:

[self performSelector:@selector(executeBlockAfterDelay:) withObject:block afterDelay:delay];

Problem

I'm trying to figure out if I do this right: If I have one block, I'll do this: ``` __weak MyClass *weakSelf = self; [self performBlock:^{ //<< Should I use self, or weakSelf here? [weakSelf doSomething]; } afterDelay:delay]; ``` But what happens if there's a block in a block? Would this be correct? ``` __weak MyClass *weakSelf = self; [self performBlock:^{ [weakSelf doSomething]; [self performBlock:^{ [weakSelf doSomething]; } afterDelay:1.0f]; } afterDelay:delay]; ``` Also, in the function below, do I need to use [block copy]? ``` - (void)performBlock:(void (^)(void))block afterDelay:(float)delay { if (block) { if (delay > 0) { [self performSelector:@selector(executeBlockAfterDelay:) withObject:[block copy] afterDelay:delay]; } else { [self executeBlockAfterDelay:[block copy]]; } } } - (void)executeBlockAfterDelay:(void(^)(void))block { if (block) block(); } ```

Original source