我们当前的best-practice for custom views是:
在笔尖中构建自定义视图。
在视图控制器中,以编程方式加载Nib,从加载的对象数组中获取自定义视图(我们在UIView类别方法+loadInstanceFromNib
中进行此操作)。
将自定义视图添加为子视图,设置其框架。
我们真正想要的是将“自定义视图Nib”“嵌入”视图控制器Nib中。失败了,至少我们要在视图控制器Nib中添加一个自定义视图实例并将其放置在其中(不查看其内容)。
我们非常接近以下解决方案:
@implementation CustomView
static BOOL loadNormally;
- (id) initWithCoder:(NSCoder*)aDecoder {
id returnValue = nil;
if (loadNormally) { // Step 2
returnValue = [super initWithCoder:aDecoder];
loadNormally = !loadNormally;
} else { // Step 1
loadNormally = !loadNormally;
returnValue = [CustomView loadInstanceFromNib];
}
return returnValue;
}
- (id) initWithFrame:(CGRect)frame {
loadNormally = YES;
self = (id) [[CustomView loadInstanceFromNib] retain];
self.frame = frame;
return self;
}
// ...
@end
如果我们以编程方式实例化自定义视图,则使用
-initWithFrame:
,它将从Nib加载视图(将调用-initWithCoder:
并直接转到标有“步骤2”的if分支),设置其框架并设置其保留数为1。但是,如果我们在视图控制器Nib中实例化自定义视图,则(非常难看)静态
loadNormally
变量最初是NO
:我们从“步骤1”开始,在该步骤中,加载并返回从其Nib加载的实例,请确保我们将立即使用-initWithCoder:
的“常规” if分支。从自定义视图Nib加载意味着我们这次使用-initWithCoder:
返回loadNormally==YES
,即我们让Nib加载机制完成其工作并返回自定义视图实例。结果总结:
优点:它有效!!!我们在Interface Builder中拥有“可插入”自定义视图!
坏处:丑陋的静态变量…:-/
丑陋:自定义视图的实例泄漏了!这就是我希望您的帮助的地方-我不明白为什么。有任何想法吗?
最佳答案
最后,我们采用了一种更好的方法,该方法涉及在自定义视图中覆盖-awakeAfterUsingCoder:
,将视图控制器Nib加载的对象替换为“嵌入式” Nib加载的对象(CustomView.xib)。
我在广泛的博客文章中写了how we embed custom-view Nibs inside other Nibs。
代码如下所示:
// CustomView.m
- (id) awakeAfterUsingCoder:(NSCoder*)aDecoder {
BOOL theThingThatGotLoadedWasJustAPlaceholder = ([[self subviews] count] == 0);
if (theThingThatGotLoadedWasJustAPlaceholder) {
// load the embedded view from its Nib
CustomView* theRealThing = [[[NSBundle mainBundle] loadNibNamed:NSStringFromClass([CustomView class]) owner:nil options:nil] objectAtIndex:0];
// pass properties through
theRealThing.frame = self.frame;
theRealThing.autoresizingMask = self.autoresizingMask;
[self release];
self = [theRealThing retain];
}
return self;
}
关于uiview - 可插拔的自定义 View Nib (Nib-in-a-Nib):内存泄漏–为什么?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/6357547/