【问题标题】:weak or strong for IBOutlet and other [duplicate]IBOutlet 和其他的弱或强[重复]
【发布时间】:2012-06-25 12:04:39
【问题描述】:

我已将我的项目切换到 ARC,但我不明白是否必须为 IBOutlets 使用 strongweak。 Xcode 这样做:在界面生成器中,例如,如果创建一个 UILabel 并且我将它与助理编辑器连接到我的 ViewController,它会创建这个:

@property (nonatomic, strong) UILabel *aLabel;

它使用strong,而不是我在 RayWenderlich 网站上阅读的教程是这样说的:

但是对于这两个特定的属性,我还有其他计划。代替 strong,我们将它们声明为weak

@property (nonatomic, weak) IBOutlet UITableView *tableView;
@property (nonatomic, weak) IBOutlet UISearchBar *searchBar;

Weak 是所有 outlet 属性的推荐关系。 这些视图对象已经是视图控制器视图的一部分 层次结构,不需要在其他地方保留。最大的优势 宣布您的网点weak 的好处是它可以节省您编写 viewDidUnload 方法。

目前我们的viewDidUnload 是这样的:

- (void)viewDidUnload
{
    [super viewDidUnload];
    self.tableView = nil;
    self.searchBar = nil;
    soundEffect = nil;
}

您现在可以将其简化为以下内容:

- (void)viewDidUnload
{
    [super viewDidUnload];
    soundEffect = nil;
}

所以使用weak,而不是strong,并将videDidUnload中的设置删除为nil,而不是Xcode使用strong,并在viewDidUnload中使用self... = nil

我的问题是:我什么时候必须使用strong,什么时候使用weak? 我也想用于部署目标 iOS 4,所以我什么时候必须使用unsafe_unretain?当使用 strongweakunsafe_unretain 与 ARC 时,任何人都可以通过一个小教程帮助我解释清楚吗?

【问题讨论】:

    标签: ios ios5 automatic-ref-counting weak-references strong-references


    【解决方案1】:

    经验法则

    当父对象引用子对象时,您应该使用strong 引用。当子对象具有对其父对象的引用时,您应该使用weak 引用或unsafe_unretained 引用(如果前者不可用)。一个典型的场景是当您与代表打交道时。例如,UITableViewDelegate 不保留包含表视图的控制器类。

    这里有一个简单的模式来展示主要概念。

    假设第一个 A、B 和 C 是 strong 引用。特别是,C 对其父级有一个strong 引用。当 obj1 被释放(某处)时,A 引用不再存在,但由于 obj1 和 obj2 之间存在循环,因此您有泄漏。就保留计数而言(仅用于解释目的),obj1 的保留计数为 2(obj2 有一个 strong 引用),而 obj2 的保留计数为 1。如果 obj1被释放,它的保留计数现在是 1,并且它的 dealloc 方法没有被调用。 obj1 和 obj2 仍然保留在内存中,但没有人引用它们:Leak

    相反,如果只有 A 和 B 是 strong refs 并且 C 是 weak ,那么一切都可以。你没有泄漏。事实上,当 obj1 被释放时,它也释放了 obj2。就保留计数而言,obj1 的保留计数为 1,obj2 的保留计数为 1。如果释放 obj1,它的保留计数现在为 0,并调用其 dealloc 方法。 obj1 和 obj2 从内存中删除。

    一个简单的建议:在处理 ARC 时开始考虑对象图。

    关于您的第一个问题,当您处理 XIB 时,两种解决方案都有效。通常在处理内存周期时使用weak 引用。 关于 XIBs 文件,如果您使用 strong,则需要在 viewDidUnload 中设置 nil,因为如果您不这样做,在内存不足的情况下,您可能会导致意外泄漏。您不会在 dealloc 中发布它们,因为 ARC 会为您完成。 weak 不需要这种处理,因为当目标对象被销毁时,这些值会自动设置为nil。不再有悬空指针。

    如果你有兴趣,我真的建议你阅读Mike Ashfriday-qa-2012-04-13-nib-memory-management

    关于你的第二个问题,如果你需要支持 iOS 4,你必须使用weak 而不是unsafe_unretained

    在 SO 中有很多问题/答案。这里是主要的:

    How do I replace weak references when using ARC and targeting iOS 4.0?

    What kind of leaks does automatic reference counting in Objective-C not prevent or minimize?

    using ARC, lifetime qualifier assign and unsafe_unretained

    strong / weak / retain / unsafe_unretained / assign

    希望对您有所帮助。

    更新

    根据 shaunlim 的评论,从 iOS 6 开始,viewDidUnload 方法已被弃用。在这里我真的建议看看 Rob 的回答:iOS 6 - viewDidUnload migrate to didReceiveMemoryWarning?

    【讨论】:

    • 你说,对于 iboutlet,如果我使用 strong 我必须在 viewdidunload 中使用 nil,而对于低内存我没有泄漏,而对于 weak 我不必在 viewdidunlaod 中使用 nil ,对于低内存警告,强解决方案还是弱解决方案更好?
    • 是一样的。使用weak 可以节省手动编写代码(在您的情况下为两行)的时间。但是,Xcode 会为您做到这一点。我的个人意见。我喜欢用strong
    • 刚遇到这个,想指出 viewDidUnload 已经被弃用了。不过,这仍然是一个非常有用的答案!
    • @shaunlim 非常感谢!我将根据您的评论更新答案。谢谢你。
    【解决方案2】:

    您可以对通过 IBOutlets 连接到 IB 中的对象的对象使用弱,因为在这种情况下,只要超级视图存在,对象就会存在。这是因为父视图有一个指向其子视图的强指针。

    如果您定义的指针是指向某个对象的唯一指针,则应将其声明为强指针。

    如果您是注册开发者,我强烈建议您观看 WWDC11 和 WWDC12 的视频。另一个很好的资源是来自Stanford.的iOS开发播客

    【讨论】:

    • WWDC12 的视频有吗?
    • 是的,他们是!今年真快。
    • 好的,但我不明白,我的问题也包括 unsafe_unretain,但对于 IBOutlet 我解释得很好,为什么苹果使用强?...而不是使用弱?...所以我一定要关注苹果吗?或者按照我在使用弱的 sn-p 上面写的 raywenderlich 教程?
    • 我的猜测是,从某种意义上说,strong 更安全,因为除了作为孩子被 superview 保留之外,这些 outlet 还会“再次”保留。想象一下,您在运行时以编程方式打开和关闭一些子视图。通过强引用,被移除的子视图会持续存在(不会被释放)。作为交换,您必须在 viewDidUnload 中将强引用设置为 nil。
    • 另一方面,如果你在 IB 中设置你的 nib 并且它永远保持这种状态(在运行时没有删除/重新添加子视图),那么 weak 应该足够了(或 'unsafe_unretained,在 pre -iOS 5)
    猜你喜欢
    • 2013-05-10
    • 1970-01-01
    • 2011-12-08
    • 2015-06-07
    • 2012-08-20
    • 1970-01-01
    • 1970-01-01
    • 2019-12-16
    • 1970-01-01
    相关资源
    最近更新 更多