在iOS上阻止保留

时间:2014-03-20 12:52:00

标签: ios objective-c-blocks retain

有人可以帮助我了解哪种方法是最好的'关于避免阻止保留周期..

__weak typeof(self) weakSelf = self;
weakSelf.myProperty = @"something";

VS

self->myProperty = @"something";

后者是xCode 5.1推荐的,前者似乎是历史推荐的。

由于

3 个答案:

答案 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->_ivarweakSelf,则会在运行时生成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没有强烈引用块,则可以在块内使用第二种语法,因为不会生成保留周期。但如果你的自己也强烈引用同一个块,那么它将产生一个保留周期。

所以你必须使用你的第一个语法,然后你可以根据你的用途在块内强化它。