我有__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];
}
答案 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;