Reputation: 9915
I have __weak reference to self. Do I need __weak reference for controller2 and controller 3 which are also referenced in the competition block ?
UIStoryboard *sb = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
id controller1 = [sb instantiateViewControllerWithIdentifier:@"controller1"];
id controller2 = [sb instantiateViewControllerWithIdentifier:@"controller2"];
id controller3 = [sb instantiateViewControllerWithIdentifier:@"controller3"];
__weak typeof(self) weakSelf = self;
[self presentViewController:controller1 animated:YES completion:^{
[(UINavigationController *)weakSelf.parentViewController setViewControllers:@[controller2, controller3] animated:NO];
}];
EDIT what about the following code? Does the block in the following code require a weak reference to self?
typedef void(^MyCustomBlock)(void);
@property (strong, readwrite, nonatomic) MyCustomBlock customBlock;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
__weak typeof(self) weakSelf = self;
self.customBlock = ^{
[(UINavigationController *)weakSelf.parentViewController setViewControllers:@[controller2, controller3] animated:NO];
};
[self presentViewController:controller1 animated:YES completion:self.customBlock];
}
Upvotes: 1
Views: 1398
Reputation: 2052
Just as addition to @danh's response, when you declare a block property do it as copy, since blocks start on the stack, and they need to be moved to the heap in order to keep a strong reference to them.
typedef void(^MyCustomBlock)(void);
@property (nonatomic, copy) MyCustomBlock customBlock;
Upvotes: 0
Reputation: 62686
Its harmless (in this case) to declare and use weak
copies, but none of the block's references need to be weak
.
The question is a symptom of a common misunderstanding: All objects to which a block refers are maintained as strong references (retained) by the block. If any those objects in turn keep a strong reference to the block, then you have a retain cycle.
Just like it sounds, a retain cycle is when objects strongly refer to each other, either directly:
block ---> objectA ---> block ("--->" means retains)
... or indirectly:
block ---> objectA ---> objectB ---> block
Retain cycles are bad because the system won't free objects that are retained by other objects. So when we try to free the block, we can't because (in the direct case) it's retained by objectA, and we can't free objectA because it's retained by the block.
The simple fix is to declare a weak
copy of the pointer, telling the block in essence "Don't retain this object. I promise it will outlive the block".
Looking at the OP code, the block passed to presentViewController
isn't retained at all. It's held long enough to do the presentation, invoked when the animation is complete and then discarded. Since none of the objects referred to by the block retain a copy of that block, there's no risk for a retain cycle, and no need for any weak
references at all.
// initialize controller1, 2, 3
// no need for this
//__weak typeof(self) weakSelf = self;
[self presentViewController:controller1 animated:YES completion:^{
// perfectly safe...
[(UINavigationController *)self.parentViewController setViewControllers:@[controller2, controller3] animated:NO];
}];
EDIT Regarding the additional code in the edit: Yes, in that case, since you retain the block and the block refers to self, a weak copy must be used in order to avoid the retain cycle.
Upvotes: 3