Search code examples
iosobjective-cobjective-c-blocksmasonry-ios-osx

When should I use weakself in a block, and why there is no retain cycle in Masonry?


UIButton *testButton = [[UIButton alloc] init];
[self.view addSubview:testButton];
testButton.backgroundColor = [UIColor redColor];
[testButton mas_makeConstraints:^(MASConstraintMaker *make) {
    make.width.equalTo(@100);
    make.height.equalTo(@100);
    make.left.equalTo(self.view.mas_left);
    make.top.equalTo(self.view.mas_top);
}];
[testButton bk_addEventHandler:^(id sender) {
    [self dismissViewControllerAnimated:YES completion:nil];
} forControlEvents:UIControlEventTouchUpInside];

I use both BlocksKit and Masonry in my code. If use I BlocksKit, bk_addEventHandler, there is a retain cycle, which I think it is because self retain self.view, retain testButton, retain self. However, when I use Mansonry alone without BlocksKit, and I use strong self in Masonry mas_makeConstraints, it occurs to me that there is no retain cycle because the viewController can invoke dealloc method. Can anyone explain to me that there is no retain cycle in Masonry?


Solution

  • It's because the block kit block is retained for execution at a later date (thus creating, thru the reference to self, the retain cycle), whereas the masonry block is executed more or less right now and then thrown away.

    Similarly, you never have to worry about a retain cycle when you call a UIView animate... method. It's because as soon as your code ends, the run loop ends and the animation block is executed and thrown away. But a reference to self in an NSNotification observer block can cause a retain cycle, because it is simply held forever by the system until you unregister for that notification, and meanwhile you are retaining the observer.