wxa*_*tly 5 cocoa cocoa-touch objective-c ios
我希望在单个块的多个调用中重用对象引用,我很好奇:以下两种方法之间的实际区别是什么?
使用__block
变量:
__block Widget *widget = [self buildNewWidget];
for(Gadget *gadget in self.gadgets) {
[self useGadget:gadget withCallback:^{
if([widget isBroken]) {
widget = [self buildNewWidget];
}
gadget.widget = widget;
}];
}
Run Code Online (Sandbox Code Playgroud)
使用static
变量:
for(Gadget *gadget in self.gadgets) {
[self useGadget:gadget withCallback:^{
static Widget *widget;
if(!widget || [widget isBroken]) {
widget = [self buildNewWidget];
}
gadget.widget = widget;
}];
}
Run Code Online (Sandbox Code Playgroud)
显然,这两个代码块在语义上是不同的,但(实际上)我认为它们做的是同样的基本工作.我的猜测是,从内存管理角度,性能角度或其他方面来看,存在差异.任何说明这些差异的见解(或解释为什么它们没有区别)都会有所帮助.
出于本答案的目的,假设这两个示例都包含在-(void)useGadgetsOnWidgets { ... }
.
假设 ARC,您的应用程序是单线程的,并且代码是不可重入的(即useGadgetsOnWidgets
不调用自身),并且在方法返回后不使用该块,则有一个主要区别:
有了static
变量,widget
就永远存在。这意味着小部件可以在调用之间重用-useGadgetsOnWidgets
(这可能是好是坏),但也意味着小部件将永远保留。您可以通过将小部件从循环/块中拉出来更改此设置(我还在开始时初始化了它以更类似于该__block
版本:
-(void)useGadgetsOnWidgets {
static Widget *widget;
widget = [self buildNewWidget];
for(Gadget *gadget in self.gadgets) {
[self useGadget:gadget withCallback:^{
if([widget isBroken]) {
widget = [self buildNewWidget];
}
gadget.widget = widget;
}];
}
widget = nil;
}
Run Code Online (Sandbox Code Playgroud)
还有第三种变体,它在某种程度上是线程安全的,并假设该方法返回后不使用该块:
-(void)useGadgetsOnWidgets {
Widget *widget = [self buildNewWidget];
Widget ** pWidget = &widget;
for(Gadget *gadget in self.gadgets) {
[self useGadget:gadget withCallback:^{
if([*pWidget isBroken]) {
*pWidget = [self buildNewWidget];
}
gadget.widget = *pWidget ;
}];
}
}
Run Code Online (Sandbox Code Playgroud)
static
这看起来比使用变量(实际上只是一个全局变量)要好一些,但它仍然很令人讨厌。这也不是我想教给新手程序员的技术(但话又说回来,也不是任何类型的多线程)。
编辑:对于您描述的问题,比这些更好的解决方案是将小部件缓存在 ivar/property 上self
:
-(Widget*)workingWidget {
// Assuming _cachedWidget is an ivar
if ([_cachedWidget isBroken]) {
_cachedWidget = [self buildWidget];
}
return _cachedWidget;
}
-(void)useGadgetsOnWidgets {
for(Gadget *gadget in self.gadgets) {
[self useGadget:gadget withCallback:^{
gadget.widget = [self workingWidget];
}];
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
534 次 |
最近记录: |