使用.xib和支持类初始化UIView的正确方法

时间:2012-08-16 18:29:07

标签: ios objective-c uiview initialization

我有一些自定义创建的UIViews,它们使用.xib文件进行布局,并使用支持类进行额外设置。我使用alloc / init创建这些类,并在我的自定义init方法中调用loadNibNamed,但这样做会导致内存泄漏。有人指出alloc部分实际上创建了一个泄漏的自我对象,所以我调整了我的init方法:

- (id)init 
{
    [self autorelease];
    self = [[[[NSBundle mainBundle] loadNibNamed:@"AssignmentView" owner:nil options:nil] lastObject] retain];
    [self setupBranding];

    UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapDetected:)];
    [self addGestureRecognizer:tapRecognizer];
    [tapRecognizer release];

    return self;
}

然而,现在当我运行分析代码时,我得到这个警告“返回'自我',而它没有设置为'[(超级或自​​我)初始化...]”的结果。所以我的问题是使用支持类进行自定义UIViews的正确方法是什么?

因为有人问我上面的代码是这样的:

AssignmentView * assignmentView = [[AssignmentView alloc] init];
[self.view addSubview:assignmentView];

2 个答案:

答案 0 :(得分:18)

从 - [NSBundle loadNibNamed:owner:options:],获取视图,然后设置其框架以匹配视图的边界。通常,您还希望在调整其父视图大小时使nib中的视图调整大小。

我们有一个UIView类别,包括以下内容:

- (UIView *)viewFromNib
{
    Class class = [self class];
    NSString *nibName = NSStringFromClass(class);
    NSArray *nibViews = [[NSBundle mainBundle] loadNibNamed:nibName owner:self options:nil];
    UIView *view = [nibViews objectAtIndex:0];
    return view;
}


- (void)addSubviewFromNib
{
    UIView *view = [self viewFromNib];
    view.frame = self.bounds;
    [self addSubview:view];
}

然后我们的-initWithFrame:方法如下所示:

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        [self addSubviewFromNib];
    }
    return self;
}

只需确保nib与该类具有相同的名称即可。

答案 1 :(得分:6)

您会考虑使用便利构造函数样式吗?

+ (AssignmentView *)assignmentView
{
    AssignmentView *result = [[[NSBundle mainBundle] loadNibNamed:@"AssignmentView" owner:nil options:nil] lastObject];
    [result setupBranding];

    UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapDetected:)];
    [result addGestureRecognizer:tapRecognizer];
    [tapRecognizer release];

    return result;
}

它为您提供构建视图时似乎需要的灵活性,但不会导致内存泄漏或警告。