为什么是addSubview:不保留视图? [英] Why is addSubview: not retaining the view?
问题描述
我将两个子视图添加到我的视图中,这两个子视图由属性存储。当我添加子视图到我的视图subViews看起来在我的设置
方法被调用后释放。最终结果是视图从不显示。现在,如果我将属性更改为 strong
,而不是 weak
,我保留对视图的引用,在屏幕上。那么这里发生了什么?为什么 addSubview:
和 insertSubview:
不保留子视图?请参阅下面的代码:
I'm adding two subviews, which are stored by properties, to my view. When adding the subviews to my view the subViews are seemingly deallocated after my setup
method is called. The end result is that the views never get displayed. Now, if I change my properties to strong
as opposed to weak
I retain a reference to the views and they now show on screen. So what's going on here? Why is the addSubview:
and insertSubview:
not retaining the subviews? See the code below:
btw,我使用iOS5与ARC(因此强和弱的东西)
btw, I'm using iOS5 with ARC (hence the strong and weak stuff)
#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生成的额外代码来了解该行中真正发生的事情。首先,发送 alloc
和 initWithFrame:
方法,返回一个强引用:
Recall that the horizontalLineView
property is weak. Let's walk through what really happens in that line, with the extra code that ARC generates. First, you send the alloc
and initWithFrame:
methods, getting back a strong reference:
id temp = [[HorizontalLineView alloc] initWithFrame:self.frame];
此时, HorizontalLineView
接下来,因为您使用点语法设置 horizontalLineView
属性,编译器生成代码以发送 setHorizontalLineView:
方法到 self
,传递 temp
作为参数。由于 HorizontalLineView
属性声明为 weak
,setter方法执行此操作:
At this point, the HorizontalLineView
object has a retain count of 1. Next, because you used dot-syntax to set the horizontalLineView
property, the compiler generates code to send the setHorizontalLineView:
method to self
, passing temp
as the parameter. Since the HorizontalLineView
property is declared weak
, the setter method does this:
objc_storeWeak(&self->_horizontalLineView, temp);
设置 self> _horizontalLineView
到 temp
,并在对象的弱引用列表中放置& self-> _horizontalLineView
。但它不会增加 HorizontalLineView
对象的保留计数。
That sets self->_horizontalLineView
equal to temp
, and puts &self->_horizontalLineView
on the object's list of weak references. But it does not increment the retain count of the HorizontalLineView
object.
因为不再需要 temp
变量,编译器生成以下内容:
Finally, because the temp
variable is no longer needed, the compiler generates this:
[temp release];
将 HorizontalLineView
对象的保留计数降低零,因此它释放对象。在释放期间,它沿着弱引用列表向下移动,并将每个设置为 nil
。 self> _horizontalLineView
成为 nil
。
That lowers the HorizontalLineView
object's retain count to zero, so it deallocates the object. During deallocation, it walks down the list of weak references, and sets each one to nil
. So self->_horizontalLineView
becomes nil
.
解决这个问题的方法是使 temp
变量显式,以便您可以延长其生命周期,直到您添加 HorizontalLineView
object to其superview,它保留了它:
The way to fix this is to make the temp
variable explicit, so that you can extend its lifetime until after you have added the HorizontalLineView
object to its superview, which retains it:
HorizontalLineView *hlv = [[HorizontalLineView alloc] initWithFrame:self.frame];
self.horizontalLineView = hlv;
// ...
[self insertSubview:hlv atIndex:0];
这篇关于为什么是addSubview:不保留视图?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!