__弱自我块

时间:2015-12-04 00:20:15

标签: objective-c

我有__weak引用自己。我是否需要控制器2和控制器3的__weak参考,这些参考也在竞争块中引用?

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

}];

编辑以下代码怎么样?以下代码中的块是否需要对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];
}

2 个答案:

答案 0 :(得分:3)

声明并使用weak副本无害(在本例中),但块的引用的需要为weak

问题是常见误解的症状:块引用的所有对象都被块保持为强引用(保留)。如果任何那些对象反过来保持对块的强引用,那么你有一个保留周期。

就像听起来一样,保留周期是指对象强烈引用彼此,直接:

block ---> objectA ---> block  ("--->" means retains)

......或间接地:

block ---> objectA ---> objectB ---> block

保留周期很糟糕,因为系统不会释放其他对象保留的对象。因此,当我们尝试释放块时,我们不能因为(在直接情况下)它被objectA保留,并且我们不能释放objectA,因为它被块保留。

简单的解决方法是声明指针的weak副本,本质上告诉块“不要保留此对象。我保证它会比块更长”。

查看OP代码,传递给presentViewController的块根本不会保留。它的持续时间足以进行演示,在动画完成后调用然后丢弃。由于块中引用的任何对象都不保留该块的副本,因此不存在保留周期的风险,并且根本不需要任何weak引用。

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

修改 关于编辑中的附加代码:是的,在这种情况下,由于您保留块并且块引用self,因此必须使用弱副本以避免保留周期。

答案 1 :(得分:0)

正如添加@ danh的响应一样,当你声明一个块属性时,将它作为副本执行,因为块从堆栈开始,并且需要将它们移动到堆中以保持对它们的强引用。

typedef void(^MyCustomBlock)(void);

@property (nonatomic, copy) MyCustomBlock customBlock;