有人可以帮助我了解哪种方法是最好的'关于避免阻止保留周期..
__weak typeof(self) weakSelf = self;
weakSelf.myProperty = @"something";
VS
self->myProperty = @"something";
后者是xCode 5.1推荐的,前者似乎是历史推荐的。
由于
答案 0 :(得分:4)
Apple真正谈论self->_ivar
语法的唯一一次是他们观察到对某个实例变量的引用,单独_ivar
实际上等同于self->_ivar
,并且因此,在块中引用_ivar
将隐含地保留self
。但他们并不是真的建议你使用self->_ivar
,只是指出与在块中使用实例变量相关的问题,它们需要隐式引用self
。
你说:
Xcode生成的“语义问题”警告。该问题被描述为“阻止隐式保留自我”。 Xcode生成的'fix-it'弹出提示'插入自我>'
我只能猜测Xcode的建议是确保对self
的隐式引用替换为显式引用,因此,当您使用weakSelf
模式时,您将能够查看每个需要替换的self
引用。很明显,Xcode很难知道__weak
self
的{{1}}版本的名称,因此很难建议,但他们提议的编辑确实有助于避免错过对{{{{{}的隐式引用。 1}}。
顺便说一句,一旦你转换那些ivar引用,例如self
,_ivar
,然后只需简单地浏览块中的代码,将self->_ivar
的引用替换为新的self
变量即可。但要小心:构造weakSelf
存在问题,因为如果weakSelf->_ivar
为weakSelf
,则会在运行时生成nil
。如果这个ivar只是支持一些属性,那么使用该属性(例如EXC_BAD_ACCESS
)。属性访问器方法正确处理weakSelf.property
指针(不执行任何操作),但取消引用nil
指针的ivar将生成nil
。
理想情况下,在这种情况下,只需使用属性访问器方法即可完成。但是,如果没有与此EXC_BAD_ACCESS
相关联的属性,则必须使用称为“_ivar
/ weakSelf
舞蹈”的模式开玩笑。所以,我们假设你的代码看起来像:
strongSelf
执行someBlockVariable = ^{
// do something
// now try to set an ivar
_ivar = ...;
};
到_ivar
更改Xcode建议,然后替换self->_ivar
,您最终会得到:
weakSelf
但这很糟糕(由于我上面描述的原因)。实际上,编译器甚至会警告您不能取消引用弱指针。所以你想要做的是:
typeof(self) __weak weakSelf = self;
someBlockVariable = ^{
// do something
// now try to set an ivar
weakSelf->_ivar = ...;
};
并且不要担心块中typeof(self) __weak weakSelf = self;
someBlockVariable = ^{
// do something
// now try to set an ivar
typeof(self) strongSelf = weakSelf;
if (strongSelf) {
strongSelf->_ivar = ...;
}
};
的引用,因为它不会保留typeof(self)
。
答案 1 :(得分:0)
这似乎很困惑。或许你看到一个例子并删除了太多的代码,这样它就再也没有意义了。
A"弱"对象指针不保留对象的保留计数,并且每当对象被释放时变为nil,这在对象丢失其最后保留计数时发生。
所以每当你看到一个"弱的"对象指针,该指针可能为零或很快变为nil。因此,像
这样的代码[weakself method1];
[weakself method2];
[weakself method3];
应该避免使用,因为在第一次或第二次调用之后,weakself可能会变为nil,并且只调用一两种方法可能会导致错误的结果。相反,你写
strongself = weakself;
[strongself method1];
[strongself method2];
[strongself method3];
强大的自我可能是零或不是,但因为它是一个强大的对象指针,它将持有对象的引用(如果它不是nil),所以将调用所有三个方法或者不调用它们。
weakself->myproperty = @"Something";
是非常危险的 - 如果弱自己是零,它会崩溃。
strongself = weakself;
strongself->myproperty = @"Something";
直接分配给实例变量很少是正确的,除了在类的实现中。
次要补充:它的前身"和"后者",而不是"后来"。这是一个拼写错误非常混乱的情况,所以你应该尽量避免这种情况。
答案 2 :(得分:0)
1.当您确定您的代码没有创建任何保留周期时,使用第二个。
2.现在出现问题
块是闭包,它们强烈引用它包含的任何对象,包括self。所以 如果self没有强烈引用块,则可以在块内使用第二种语法,因为不会生成保留周期。但如果你的自己也强烈引用同一个块,那么它将产生一个保留周期。
所以你必须使用你的第一个语法,然后你可以根据你的用途在块内强化它。