为什么是addSubview:不保留视图?

我添加了两个子视图,这些子视图通过属性存储在我的视图中。 将子视图添加到我的视图时,在我的setup方法被调用后,子视图似乎被解除分配。 最终的结果是,视图永远不会显示。 现在,如果我改变我的属性,而不是weak我保留一个参考的意见,他们现在显示在屏幕上。 那么这里发生了什么? 为什么是addSubview:insertSubview:不保留子视图? 请参阅下面的代码:

顺便说一句,我使用ARC5的iOS5(因此强大和弱的东西)

 #import "NoteView.h" @interface NoteView() <UITextViewDelegate> @property (weak, nonatomic) HorizontalLineView *horizontalLineView; // custom subclass of UIView that all it does is draw horizontal lines @property (weak, nonatomic) UITextView *textView; @end @implementation NoteView @synthesize horizontalLineView = _horizontalLineView; @synthesize textView = _textView; #define LEFT_MARGIN 20 - (void)setup { // Create the subviews and set the frames self.horizontalLineView = [[HorizontalLineView alloc] initWithFrame:self.frame]; CGRect textViewFrame = CGRectMake(LEFT_MARGIN, 0, self.frame.size.width, self.frame.size.height); self.textView = [[UITextView alloc] initWithFrame:textViewFrame]; // some addition setup stuff that I didn't include in this question... // Finally, add the subviews to the view [self addSubview:self.textView]; [self insertSubview:self.horizontalLineView atIndex:0]; } - (void)awakeFromNib { [super awakeFromNib]; [self setup]; } - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { // Initialization code [self setup]; } return self; } 

这是你的代码的一行:

 self.horizontalLineView = [[HorizontalLineView alloc] initWithFrame:self.frame]; 

回想一下, horizontalLineView属性很弱。 让我们来看看这一行中真正发生的事情,用ARC生成的额外代码。 首先,你发送allocinitWithFrame:方法,得到一个强有力的参考:

 id temp = [[HorizontalLineView alloc] initWithFrame:self.frame]; 

此时, HorizontalLineView对象的保留计数为1.接下来,由于您使用了dot-syntax来设置horizontalLineView属性,因此编译器会生成将setHorizontalLineView:方法发送给self ,并将temp作为parameter passing。 由于HorizontalLineView属性被声明为weak ,setter方法执行此操作:

 objc_storeWeak(&self->_horizontalLineView, temp); 

这将self->_horizontalLineView等于temp ,并将&self->_horizontalLineView放置在对象的弱引用列表中。 但是它不会增加HorizontalLineView对象的保留计数。

最后,因为tempvariables不再需要,编译器生成这个:

 [temp release]; 

这将HorizontalLineView对象的保留计数降低到零,因此它将取消分配对象。 在释放期间,它沿着弱引用列表行进,并将每个引用设置nil 。 所以self->_horizontalLineView成为nil

解决这个问题的方法是使tempvariables显式化,这样就可以延长它的生命周期,直到将HorizontalLineView对象添加到它的超级视图中,并保留它:

 HorizontalLineView *hlv = [[HorizontalLineView alloc] initWithFrame:self.frame]; self.horizontalLineView = hlv; // ... [self insertSubview:hlv atIndex:0]; 

除非亲子保留周期形成的情况下(父母保留对孩子的引用,孩子保留对父母的引用,否则都不被释放),否则不应使用弱。 Strong是ARC的等价保留(现在在ARC下无效),并且在一个比弱引用长得多的时间内保持一个很好的稳定的指向对象的指针,因此addSubview实际上起作用,而不是给你一些错误。

为什么是addSubview:和insertSubview:不保留子视图?

你有没有试过在一个零对象上调用retain? 对,还没有。 你的弱引用不能让UIView对象保持足够长的时间来成功地在对象上调用retain。

尝试使用此代替:

  @property (nonatomic, retain)