关于ios:自定义UIView子视图的最佳实践强弱对弱

Best practice for custom UIView subview strong vs weak

所以我正在编写一个从uiview继承的自定义类。我加了一堆子视图。

所以遇到两个问题。如果我使超级视图和子视图引用很强,那么视图就会泄漏。如果我让他们软弱,他们就不会出现。我做错什么了?

定制视图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@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

其他自定义视图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@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


基于您的代码,我认为您混淆了强引用和弱引用,以及它们与内存管理的关系。

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

在您的具体案例中,AnotherCustomUIView上的ownerView属性应该是弱的,因为它指向一个高级对象。代表参考也很弱,我不知道设置self.delegate = self;有任何负面影响。

编辑:

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

1
2
[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:


几乎总是对父级的引用应该是弱的。这是典型的指挥链。父母创造并"拥有"孩子,而孩子只是观察自己的父母。你希望孩子存在地依赖于父母,而不是相反。