为什么是addSubview:不保留视图? [英] Why is addSubview: not retaining the view?

查看:71
本文介绍了为什么是addSubview:不保留视图?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我将两个子视图添加到我的视图中,这两个子视图由属性存储。当我添加子视图到我的视图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];

记住 horizo​​ntalLineView 属性很弱。让我们通过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];

此时, Horizo​​ntalLineView 接下来,因为您使用点语法设置 horizo​​ntalLineView 属性,编译器生成代码以发送 setHorizo​​ntalLineView:方法到 self ,传递 temp 作为参数。由于 Horizo​​ntalLineView 属性声明为 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> _horizo​​ntalLineView temp ,并在对象的弱引用列表中放置& self-> _horizo​​ntalLineView 。但它不会增加 Horizo​​ntalLineView 对象的保留计数。

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];

Horizo​​ntalLineView 对象的保留计数降低零,因此它释放对象。在释放期间,它沿着弱引用列表向下移动,并将每个设置为 nil self> _horizo​​ntalLineView 成为 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 变量显式,以便您可以延长其生命周期,直到您添加 Horizo​​ntalLineView 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆