2012-08-16 37 views
8

我有一些使用.xib文件进行布局的自定义创建的UIViews,以及用于额外安装的支持类。我使用alloc/init创建这些类,并在我的自定义init方法中调用loadNibNamed,但这样做会导致内存泄漏。有人指出,页头部分实际上创造了漏水所以自对象我调整我的init方法来这样一句:使用.xib和支持类初始化UIView的正确方法

- (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; 
} 

但是,现在当我运行分析代码,我得到这样的警告“回归自我“,而它没有设置为'[(super或self)init ...]'“的结果。所以我的问题是什么是做一个支持类的自定义UIViews的正确方法?

既然有人问我会用这上面的代码是这样的:

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

一般来说,如果你从xib载入一个视图,你应该通过'loadNibNamed'在你创建它的任何类中加载它,然后在它的'awakeFromNib'方法中设置它,甚至不用接触'init' 。无论如何,这是我的经验。你可能在实例化视图的时候添加一些代码,以及你的'awakeFromNib'方法吗? – 2012-08-16 19:26:33

+1

我想你会在你的方法的顶部添加'self = [super init]'。保罗是对的,因为你通常不会在内部进行笔尖加载。 – Dustin 2012-08-16 19:26:45

+0

谢谢,我一直试图避免整个loadNibNamed,只是使用[[MyView alloc] init],但如果我不得不重新工作,而是使用loadNibNamed,那么我想我必须。我没有一个awakeFromNib方法,但init中的所有内容都会去那里。 – 2012-08-16 23:31:48

回答

17

从视图 - [NSBundle loadNibNamed:owner:options:],然后设置其框架以符合您的视图边界。通常,您还需要在调整父视图的大小时调整其大小。

我们已经有了一个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; 
} 

只要确保笔尖具有相同的名称这个班的工作。

+0

另一个有趣的解决方案。我喜欢这个,因为我不必改变我已经在使用我的观点 – 2012-08-17 17:56:12

+0

我知道这是旧的,但这是一个很好的解决方案,正是我希望做的。 – Armand 2017-08-11 04:42:24

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

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

+0

有趣的,我会给这个镜头。 – 2012-08-17 17:52:33