我正在添加两个由属性存储的子视图到我的视图中。将子视图添加到我的视图时,在调用setup
方法后,子视图似乎已取消分配。最终结果是视图永远不会显示。现在,如果我将我的属性更改为strong
而不是weak
,我会保留对视图的引用,现在它们将显示在屏幕上。那么这里发生了什么?为什么addSubview:
和insertSubview:
没有保留子视图?请参阅以下代码:
#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;
}
答案 0 :(得分:21)
以下是您的代码行:
self.horizontalLineView = [[HorizontalLineView alloc] initWithFrame:self.frame];
回想一下horizontalLineView
属性很弱。让我们通过ARC生成的额外代码,了解该行中真正发生的事情。首先,您发送alloc
和initWithFrame:
方法,获得强大的参考资料:
id temp = [[HorizontalLineView alloc] initWithFrame:self.frame];
此时,HorizontalLineView
对象的保留计数为1.接下来,因为您使用了点语法来设置horizontalLineView
属性,所以编译器会生成代码以发送{{1}方法setHorizontalLineView:
,传递self
作为参数。由于temp
属性声明为HorizontalLineView
,因此setter方法执行此操作:
weak
设置objc_storeWeak(&self->_horizontalLineView, temp);
等于self->_horizontalLineView
,并将temp
放在对象的弱引用列表中。但它不增加&self->_horizontalLineView
对象的保留计数。
最后,因为不再需要HorizontalLineView
变量,编译器会生成:
temp
将[temp release];
对象的保留计数降低为零,因此它会释放该对象。在解除分配期间,它会向下遍历弱引用列表,并将每个引用设置为HorizontalLineView
。因此nil
变为self->_horizontalLineView
。
解决此问题的方法是使nil
变量显式化,以便您可以延长其生命周期,直到将temp
对象添加到其超级视图后保留它:
HorizontalLineView
答案 1 :(得分:3)
除非在父母子女保留周期形成的情况下(父母保留对孩子的引用,孩子保留对父母的引用,因此两者都不被dealloc'd),否则不应该使用弱。强与ARC相当于retain(现在在ARC下无效),并且保持一个很好的稳定指针指向对象的时间比弱引用长得多,因此addSubview实际上可以工作,而不是给你一些错误。
为什么addSubview:和insertSubview:不保留子视图?
你有没有试过在零对象上调用retain?是的,仍然没有。你的弱引用并没有将UIView对象保持足够长的时间,以便在对象上成功“调用retain”。
答案 2 :(得分:0)
请尝试使用此代码:
@property (nonatomic, retain)