弱参考和保留周期

时间:2014-04-02 03:14:52

标签: ios objective-c weak-references

我正在开发一个使用ARC的应用程序,所以我有3个案例:

1 @property (strong, nonatomic) IBOutlet UILabel *titleLabel;

这意味着:titleLable强烈引用superViewsuperView强烈引用titleLabel

2 @property (weak, nonatomic) IBOutlet UILabel *titleLabel;

这意味着:titleLablesuperView的引用较弱而superViewtitleLabel有强烈的引用?

3我宣布:

UILabel *titleLabel = [[UILabel alloc] initWithFrame:self.view.bounds];
[self.view addSubview:titleLabel]

每个人都可以回答我的问题吗?

  • 我对案例1和案例2的描述是否正确?

  • 在案例1中,superView是否可以发布?因为我认为titleLable强烈引用supperView

    • 在案例3中,为什么我们不需要为__weak声明titleLabel,在这种情况下可能会释放superView? 谢谢你的回复。

4 个答案:

答案 0 :(得分:2)

我将假设titleLabel是UIViewController中的属性。

1.1 - UIViewController对titleLabel有强烈的引用。 titleLabel没有引用UIViewController。

2.2 - UIViewController对titleLabel有一个弱引用。 titleLabel没有引用UIViewController。 titleLabel只有在某处有强烈的引用时才会被保留。将其添加到视图层次结构将作为强引用。

3.3 - 在这种情况下,UIViewController对titleLabel有一个强引用,直到它超出范围。但是,您将它添加到视图层次结构中,该层次结构将保留它直到其超级视图离开视图层次结构。

答案 1 :(得分:2)

澄清最佳做法重新IBOutlet引用,正如Resource Programming Guide: Nib Files文档所述:

  

每当您要求NSBundleNSNib类加载nib文件时,底层代码会在该文件中创建对象的新副本并将它们返回给您。 (nib加载代码不会从先前的加载尝试中回收nib文件对象。)您需要确保在必要时维护新的对象图,并在完成它时将其取消。您通常需要strong对顶级对象的引用,以确保它们不被取消分配;你不需要strong引用图中较低的对象,因为它们是由父母拥有的,你应该尽量减少创建强引用周期的风险。

     

从实际角度来看,在iOS和OS X中,出口应该被定义为声明的属性。出口通常应为weak,除了从文件所有者到nib文件(或iOS,故事板场景)中的顶级对象(应为strong)。因此,您创建的出口通常应为weak,因为:

     
      
  • 例如,您创建到视图控制器视图或窗口控制器窗口的子视图的出口是不暗示所有权的对象之间的任意引用。

  •   
  • strong出口通常由框架类指定(例如,UIViewController的{​​{1}}出口或view的{​​{1}}出口)。

  •   

请注意,虽然这只是对故事板的一个括号内容,但大多数讨论同样适用于NIB的故事板。

因此,如果您的标签是您在Interface Builder中连接的NSWindowController,请使用window

如果您执行IBOutlet手动实例化标签,那么weak将确保视图为您保留对标签的addSubview引用(直到您将其删除为止)从addSubview,或者该视图本身,已取消分配),因此您不需要保留任何其他strong引用,也不需要担心它被释放时局部变量超出范围。

答案 2 :(得分:2)

这里的其他答案都很好,但我想更清楚你似乎有一种误解。类的属性是单向关系,而不是两个。

因此,在每种情况下,您都会询问该属性如何引用其所有者(强或弱),但实际情况是它根本没有引用它。事实上,在任何给定时间,没有任何对象知道其他对象拥有它。它唯一跟踪的是有多少对象拥有它。如果你想要一个双向关系,两个对象都有一个彼此的引用,那就是你需要在至少一个方向上有一个弱引用。否则,两个对象都确保其他对象永远不会被释放,因此也不会被释放。这就是所谓的循环参考"。它可能发生在两个以上的对象之间,其中A具有对B的强引用,B具有对C的强引用,并且C具有对A的强引用。

现在,关于" superview" UIViews上的方法。这将始终是一个弱引用,并在添加子视图时自动设置。这是因为父视图始终具有对其所有子项的强引用。如果一个孩子对其父母有强烈的引用,那么就会有一个循环引用。但请注意,向视图添加属性不会自动将其添加为子视图,但仍必须在代码中或在xib或storyboard中手动完成。

因此,简而言之,只有案例3在视图和标签之间创建引用,因为您将其添加为子视图。然后self.view对标签有很强的参考价值。作为一种完全不同的机制,视图然后在子视图上添加一个弱引用,称为" superview"。

答案 3 :(得分:1)

在案例1中,您的对象(可能是视图控制器)强烈引用titleLabel。该财产的声明并未告诉我们标签的超级视图(可能是titleLabel,而不是self.view)对self的引用。您可以假设self.view是一个强引用,您可以假设该视图将保留对其子视图的强引用 - 其中titleLabel是一个 - 并且titleLabel将保留弱引用它的超级视角。

在案例2中,您的对象具有对titleLabel的弱引用。这不会改变对象保存对其视图的引用的方式,也不会更改该视图如何保存对其子视图的引用,也不会更改titleLabel如何保存对其超级视图的引用。

在案例3中,弱引用将起作用,因为通过视图层次结构保留了足够的引用,以防止titleLabel过早释放。

在所有情况下,将通过视图控制器生命周期方法处理对象的释放,这些方法确保在删除视图控制器时以递归方式删除视图及其子视图