在Objective-C中,将weak
分配给块中的strong
是什么意思?现场背后发生了什么?
e.g。
__weak __typeof(self) wself = self;
void (^cmd)() = ^(){
__strong __typeof(self) sself = wself;
if (!sself) return;
...
};
答案 0 :(得分:9)
这里的意图有两个方面:
首先,是使用:
__weak __typeof(self) wself = self;
这可确保cmd
块不会保留对self
的强引用。这确保了,如果cmd
是类的实例变量,那么您最终不会得到强引用循环。如果不使用此wself
模式,那么将cmd
作为实例变量的类永远不会被释放,并且您将泄漏具有cmd
的对象作为实例变量。
有关详细信息,请参阅使用Objective-C编程:使用块文档的Avoid Strong Reference Cycles when Capturing self部分。
其次,在块内使用以下内容:
__strong __typeof(self) sself = wself;
if (!sself) return;
这确保了,如果块开始执行,如果wself
已经被释放,则该块将退出。但是,如果尚未释放wself
,则通过分配sself
,您确保在执行块期间将保留该对象。
此外,如果您引用块中的任何ivars,请注意您要取消引用它们(因为否则块中存在对self
的隐式引用,可能导致该强引用循环)。但是你不能使用弱指针取消引用ivars(例如不允许使用wself->someIvar
),但你可以使用这个本地强指针(例如sself->someIvar
)。一般来说,你不应该取消引用ivars,而是使用属性,但是使用本地强引用self
是另一个原因。
通常,您会看到此构造与类属性(或ivar)结合使用:
@property (nonatomic, copy) void (^commandBlock)(void);
而且,作为惯例,您通常会看到更多描述性变量名称weakSelf
和strongSelf
,因此:
__weak __typeof(self) weakSelf = self;
self.commandBlock = ^(){
__strong __typeof(self) strongSelf = weakSelf;
if (!strongSelf) return;
...
};
当您拥有自己的类属性并且希望(a)阻止强引用周期(也称为保留周期)时,此weakSelf
/ strongSelf
模式非常常见;但是(b)希望确保在执行块的过程中不能释放有问题的对象。
答案 1 :(得分:5)
如果您没有为weak
分配strong
引用,则weak
引用引用的对象可以在块执行过程中释放 - 这可能是您不期望的。如果分配给strong
,只要强引用在范围内,该对象就会被保留(除非该对象在分配之前已经被释放)。
当您为强编译器分配弱引用时,将Objective-C运行时函数调用插入到代码中,该代码根据需要递增对象引用计数器以保留它。当强变量超出范围时(或更早,在最后一次使用强变量之后),编译器插入的另一个调用会减少引用计数器。