【问题标题】:Best practice for custom UIView subview strong vs weak自定义 UIView 子视图强与弱的最佳实践
【发布时间】:2013-07-05 05:39:56
【问题描述】:

所以我正在编写一个继承自 UIView 的自定义类。我有一堆子视图,我添加了。

因此遇到 2 个问题。如果我使超级视图和子视图引用强,则视图正在泄漏。如果我让他们变得虚弱,他们根本就不会出现。我做错了什么?

自定义UIView

@interface CustomUIView : UIView
@property(nonatomic, strong) AnotherCustomUIView *mySubView;
@end

@implementation CustomUIView {

- (void)initCommon {
    self.mySubView = [self createSubView]
}

- (AnotherCustomUIView *) createSubView {
    return [[AnotherCustomUIView alloc] init:self];
}

@end

另一个CustomUIView

@interface AnotherCustomUIView : UIScrollView
@property (nonatomic, strong) CustomUIView *ownerView;
@end


@implementation AnotherCustomUIView

- (id)init:(CustomUIView *) ownerView {
    self = [super init];
    if (self) {
        self.ownerView = ownerView;
        self.delegate = self;
    }
    return self;
}

@end

【问题讨论】:

  • 一个强一个弱,这样你就可以避免保留周期和过早的释放。看在上帝的份上,不要调用你的初始化器init:
  • 是的,我刚刚编写了一些代码来演示。 init 实际上是 initWithOwner。 AnotherCustomUIView 是一个虚拟滚动视图,它具有计算其内容应该有多大并响应滚动的逻辑,所以我将自己设置为滚动视图委托。我应该采取不同的做法吗?这会导致内存问题吗?代表应该很弱吧?
  • @userXXX 恰好其中一个 应该是弱的,实际上哪个不重要,但考虑一下(毕竟,这是你自己的代码),然后决定你将制作哪一个strong

标签: ios objective-c memory-management


【解决方案1】:

几乎总是对父级的引用应该是弱的。这是典型的指挥链。父级创建并“拥有”子级,而子级仅观察其父级。您希望孩子在存在上依赖于父母,而不是相反。

【讨论】:

    【解决方案2】:

    根据您的代码,我认为您对强引用和弱引用以及它们与内存管理的关系存在混淆。

    首先,这里是强与弱的一个很好的描述:https://stackoverflow.com/a/11013715/700471

    在您的具体情况下,AnotherCustomUIView 上的 ownerView 属性应该很弱,因为它指向高级对象。委托引用也很弱,不知道设置self.delegate = self;有什么负面影响。

    编辑:

    为了澄清,添加一个视图作为另一个视图的子视图会创建一个对它的strong引用。一旦您的视图是视图层次结构的一部分,就不需要进一步的强引用。所以你有这个代码:

    [mySeniorView addSubView:myJuniorView]; // myJuniorView will not be released.
    mySeniorView.juniorView = myJuniorView; // This shouldn't be a strong reference.
    

    在上面的代码中,如果mySeniorView.juniorView 是强引用,那就是多余的。如果您从视图层次结构中删除myJuniorView,它将不会被释放,因为您还有另一个对它的强引用。如果.juniorView 是弱引用,则从视图层次结构中删除myJuniorView 将导致其解除分配并将.juniorView 设置为nil

    这就是为什么,例如,您的所有 IBOutlet 属性都应该是弱的;因为您将它们连接到的 xib 中的东西是视图层次结构的一部分,因此不会解除分配,因为它们的高级视图对它们有很强的引用。

    所以, 虽然我指出您的初级对象不应该对您的高级对象有强引用(两者都不会释放;这称为保留周期并导致内存泄漏)可能是您的高级对象不应该对您的初级对象有强引用,除非您希望它即使不在视图层次结构中也能挂起。毕竟,这些都是观点;我会说创建你的初级对象,将它弹出到视图层次结构中,然后在弱属性中保存对它的引用,这样只要它存在,你就可以访问它。然后,当您将其从视图层次结构中删除时,您的引用将无效。

    无论如何,希望对您有所帮助。

    参考:Apple Docs, addSubview:

    【讨论】:

    • 谢谢 - 我猜困惑来自我的信念,即将 ownerView 添加到它自己的 superView 会固有地创建一个强引用,所以如果我将两个引用都设为弱引用,我会好的,但我会这样做你建议,这是有道理的,而且是我前进的方向。感谢您的确认。
    • 嗯...将视图作为子视图添加到另一个视图确实会创建强引用。我编辑了我的帖子以澄清一点。
    • 我不认为持有对拥有对象的多个强引用有不利之处。它们是免费的,并且在所有者解除分配时都会减少。弱引用也更昂贵,因为系统需要跟踪它们以履行自动零合约......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-30
    • 1970-01-01
    • 2014-03-20
    • 2012-09-20
    • 2013-11-04
    相关资源
    最近更新 更多