weak属性调用objc_storeStrong

时间:2012-08-04 00:29:12

标签: ios automatic-ref-counting

我有一个名为Panel的类,它包含一个像以下这样的弱属性:

@property(非原子,弱)Dialog *容器;

在Instruments中,我可以看到setContainer方法最终调用了objc_storeStrong。

这是对的吗?我认为弱的属性并没有增加保留计数。

我的init方法如下:

- (id) initWithContainer:(Dialog *)pContainer{
    self = [self init];
    if (self) {
        self.container = pContainer;
    }
    return self;
}

请指教。 谢谢,

3 个答案:

答案 0 :(得分:1)

在调试此问题时,感谢大家的帮助。我非常感谢。我的知识是正确的,弱的不会增加保留计数。不幸的是,我花了几个小时来调试这个问题,结果是仪器拿起了一个旧版本的应用程序,这个版本是在没有财产变弱的情况下构建的。我不知道这是怎么发生的,因为我是从Xcode项目中发射仪器,做了一个干净的等等...但是有些事情是错的,因为当我启动仪器时它会问我两次仪器,而不是一次,然后自动启动应用程序,我将不得不通过选择目标手动启动它(这是错误的,因为它通常会自动启动应用程序。)我通过退出仪器,Xcode和模拟器并再次重新启动来解决问题。谢谢!

答案 1 :(得分:0)

您应该收到objc_storeStrong消息,但不会发送到容器属性。它被发送到您的arg,因为局部变量会自动强大并保留(如果未指定weak),并保留在赋值中。当你的方法返回时,arc会自动为你释放arg。

答案 2 :(得分:0)

使用乐器的荣誉。

首先,您应该直接在init / dealloc中使用iVar。

其次,你自己合成它,还是自己实现setter?

此外,您是否正在运行调试或发布优化代码?

现在,解释为什么我回答你的问题还有更多问题。

如果您自己合成它(即声明自己的实例变量,您还必须将其声明为__weak。如果您让编译器执行它,它将正确处理它。

现在,您显然正在使用ARC。因此,编译器将自动添加代码以执行手动引用计数(其中一些可能稍后由优化器删除)。现在,我并不假装自己是编译器自动创建的专家,但它将非常接近以下内容。

以基本作业为例......

- (void)setContainer(Container*)container {
    _container = container;
}

当编译器完成注入其ARC代码时,这看起来就像(假设_container未声明为__weak)......

// Converted by ARC -- so it's MRC
- (void)setContainer(Container*)container {
    [container retain];
    Container *oldContainer = _container;
    _container = [container retain];
    [oldContainer release];
    [container release];
}

现在,让我们更进一步,假设_container是__weak,我们得到这样的东西......

- (void)setContainer(Container*)container {
    [container retain]
    Container *oldContainer = [_container retain];
    objc_storeWeak(&_container, container);
    [oldContainer release];
    [container release];
}

现在,objc_storeStrong是分配给强变量的序列,所以很明显它适用于上面的代码。

另外,请注意,编译器在添加代码方面是明智的。优化器非常具有攻击性,可以删除大多数显然不需要的保留/释放对。因此,在大多数情况下,您将看到函数中保留/释放的不同语义,具体取决于您是构建调试还是发布。

但是,一般情况下,除非指定为__unsafe_unretained,否则您必须至少获得任何参数的保留。