我在纯iOS5 / ARC环境中工作,所以我可以根据需要使用__weak引用。在很多情况下我都会在块中引用ivars,最值得注意的是,移动视图的动画块,比如我的视图控制器类的属性。
在一个区块中最简单地使用ivars,我是否创建了一个参考周期?我是否需要每次都使用__weak self / strong self技术 我编写了一个操作包含对象的实例变量的块?
我一直在重新观看2011年WWDC会议#322(Objective-C深度进展),以了解从时间索引25:03开始的关于“通过捕获自我的参考周期”的3分钟段的细微差别。对我来说,这意味着任何块中ivars的使用都应该通过该段中描述的弱自我/强自我设置来保护。
以下是视图控制器上的示例方法,是我做过的典型动画。
在openIris块中,像我一样引用ivars“_topView”和“_bottomView”是错误的吗?
我是否应始终在块之前设置__weak引用自身,然后在块内强引用刚刚设置的弱引用,然后通过我块中的强引用访问ivars?
在WWDC会话中,我理解在块中引用ivars实际上是在创建对这些ivars挂起的隐含自我的引用。
对我而言,这意味着没有任何简单或无关紧要的情况,在没有弱/强舞的情况下访问块中的ivars是正确的,以确保没有循环。或者我是否正在阅读一个不适用于简单案例的角落案例,例如我的例子?
- (void)openIrisAnimated:(BOOL)animated
{
if (_isIrisOpened) {
NSLog(@"Asked to open an already open iris.");
return; // Bail
}
// Put the common work into a block.
// Note: “_topView” and “_bottomView” are the backing ivars of
// properties “topView” and “bottomView”
void (^openIris)() = ^{
_topView.frame = CGRectMake(....);
_bottomView.frame = CGRectMake(....);
};
// Now do the actual opening of the iris, whether animated or not:
if (animated) {
[UIView animateWithDuration:0.70f
animations:^{
openIris();
}];
}
else {
openIris();
}
_irisOpened = YES; // Because we have now just opened it
}
以下是我如何使用Session#322的指导重新编写openIris块块,但我只是想知道我所有类似的块是否需要这种弱/强参考舞以确保正确性和稳定性:
__weak MyClass *weakSelf = self;
void (^openIris)() = ^{
MyClass *strongSelf = weakSelf;
if (strongSelf) {
strongSelf.topView.frame = CGRectMake(....);
strongSelf.bottomView.frame = CGRectMake(....);
}
};
这实际上是必要的吗?
答案 0 :(得分:21)
如果self继续持有对块的引用(或者self拥有的东西),那么这里只有一个循环。如果不是你就好了,因为它的生命周期不是由它保留的自我决定的。
所以在你的特定例子中,你似乎很清楚。动画块不需要参加弱/强自我舞蹈。
答案 1 :(得分:4)
担心的情况类似于addObserverForName:object:queue:usingBlock:
。文档说:“该块由通知中心复制。”在ARC下,“复制”一词是一面红旗;现在你需要采取措施让你(来电者)不会泄漏。
编辑:此外,有时ARC本身会提醒您。 -[UIPageViewController setViewControllers:direction:animated:completion:]
的完成块就是一个例子。我永远不会怀疑在这里使用self
可能会导致保留周期,但ARC警告它会这样做,所以我做了弱强舞以防万一。