我有一些自定义创建的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];
答案 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;
}
它为您提供构建视图时似乎需要的灵活性,但不会导致内存泄漏或警告。