我在 View 中添加了两个按属性存储的 subview 。当将 subview 添加到我的 View 时,在调用我的setup方法之后,该 subview 似乎被释放了。最终结果是 View 永远不会显示。现在,如果我将属性更改为strong而不是weak,则保留对 View 的引用,它们现在显示在屏幕上。那么这是怎么回事?为什么addSubview:insertSubview:不保留 subview ?请参见下面的代码:

顺便说一句,我正在将iOS5与ARC配合使用(因此,强项和弱项)

#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。接下来,因为您使用点语法设置了horizontalLineView属性,所以编译器生成了将setHorizontalLineView:方法发送给self的代码,并通过temp作为参数。由于HorizontalLineView属性被声明为weak,因此setter方法将执行以下操作:
objc_storeWeak(&self->_horizontalLineView, temp);

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

最后,由于不再需要temp变量,因此编译器将生成以下代码:
[temp release];

这样可以将HorizontalLineView对象的保留计数降低为零,因此可以取消分配该对象。在解除分配期间,它将沿弱引用列表走动,并将每个引用设置为nil。因此self->_horizontalLineView变成nil

解决此问题的方法是使temp变量显式,以便您可以延长其生存期,直到将HorizontalLineView对象添加到其 super View 中为止(保留它):
HorizontalLineView *hlv = [[HorizontalLineView alloc] initWithFrame:self.frame];
self.horizontalLineView = hlv;
// ...
[self insertSubview:hlv atIndex:0];

关于iphone - 为什么addSubview : not retaining the view?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9747015/

10-10 20:40