调用 UIView initWithFrame 即使从 NIB 加载 self ? [复制]
Posted
技术标签:
【中文标题】调用 UIView initWithFrame 即使从 NIB 加载 self ? [复制]【英文标题】:call UIView initWithFrame even when self is loaded from NIB? [duplicate] 【发布时间】:2016-07-11 09:41:42 【问题描述】:我继承了一个代码库,发现编译器抱怨这段代码:
- (id)initWithFrame:(CGRect)frame
// is this really missing??
// self = [super initWithFrame:frame];
self = [[[NSBundle mainBundle] loadNibNamed:@"DigitsKeyboardView" owner:self options:nil] firstObject];
return self;
XCode 抱怨超类中的指定初始化程序没有被调用。如果我取消注释对 super 的调用,错误就会明显消失。但是由于该应用程序并没有为相当多的 ios 版本缺少该行而烦恼,我不确定这是否是一个学术要求,或者在这种情况下甚至可能是错误的。
loadNibNamed
方法用self
调用,然后self
被覆盖。这会导致无法立即看到的问题吗?
在这种情况下,正确的实现是什么?
【问题讨论】:
【参考方案1】:initWithFrame - 初始化并返回一个新分配的具有指定框架矩形的视图对象。 视图的框架矩形,以磅为单位。框架的原点是相对于您计划在其中添加它的超级视图。此方法使用框架矩形来相应地设置中心和边界属性。
参数是帧 - 视图的框架矩形,以磅为单位。框架的原点与您计划添加它的 superview 相关。此方法使用框架矩形来相应地设置中心和边界属性。
所以你应该像这样在下面调用
- (id)initWithFrame:(CGRect)frame
self = [super initWithFrame:frame];
if (self)
// Initialization code
NSArray *arrNibView = [[NSBundle mainBundle] loadNibNamed:@"DigitsKeyboardView" owner:self options:nil];
UIView *nibView = (UIView*)[arrNibView objectAtIndex:0]; //Give here your first object
[self addSubview:nibView];
return self;
如果您有多个自定义视图,并且如果您想将自定义视图用于单独的控制器,您可以使用上述方法。
但是如果你有自定义视图并且如果你想使用(重用)多个 在多个视图控制器中,您需要同时实现 bot initWithFrame 和 awakeFromNib 方法
- (id)initWithFrame:(CGRect)frame
self = [super initWithFrame:frame];
if (self)
// Initialization code
[[NSBundle mainBundle] loadNibNamed:@"DigitsKeyboardView" owner:self options:nil];
[self addSubview:self.view];
return self;
- (void) awakeFromNib
[super awakeFromNib];
[self addSubview:self.view];
initWithFrame - 建议您实现此方法。你 还可以实现自定义初始化方法,或者 而不是这种方法。
awakeFromNib - 在视图及其视图之后调用 awakeFromNib 子视图被分配和初始化。保证 视图将设置其所有出口实例变量。
awakeFromNib详解
在实例化过程中,存档中的每个对象都是 未归档,然后使用适合其类型的方法进行初始化。 Cocoa 视图(以及可以使用 相关的 Interface Builder 调色板)使用它们的初始化 initWithCoder:方法。自定义视图使用它们的初始化 initWithFrame:方法。已实例化的自定义类 笔尖使用它们的 init 方法进行初始化。
一旦所有对象都被实例化并从存档中初始化,nib 加载代码会尝试重新建立连接 在每个对象的出口和相应的目标对象之间。如果 您的自定义对象有出口,一个 NSNib 对象试图 重新建立您在 Interface Builder 中创建的任何连接。它 首先尝试使用您的对象自己建立连接 先说方法。对于每个需要连接的插座,NSNIb object 在您的对象中查找形式为 setOutletName: 的方法。 如果该方法存在,则 NSNib 对象调用它,并传递目标 对象作为参数。如果你没有用那个定义一个 setter 方法 确切的名称,NSNIb 对象在对象中搜索实例 具有相应出口名称的变量(IBOutlet id 类型)和 尝试直接设置其值。如果一个实例变量带有 找不到正确的名称,该连接的初始化确实 不会发生。最后,在所有对象完全初始化后,每个 收到一条 awakeFromNib 消息。
苹果文档
UIView
initWithFrame
awakeFromNib
其他来源
Getting Nib File loaded
Initialize a view with xib
awakeFromNib Calling
viewDidLoad and awakeFromNib timing
【讨论】:
感谢您的详细解释。评论指出,我在重复问题的来源中找到了实现它的正确方法。我在您的回答中缺少的实际上是当我将子视图返回为self
时的后果。由于它已经工作了多年,我怀疑 iOS 并没有太大的问题。我想,我们与最初分配的视图失去了联系,并且在离开 initWithFrame 方法后,可能有一个创建的对象没有被 ARC 存储和删除。在实现时,它是loadFromNib
的一种昂贵的包装器。以上是关于调用 UIView initWithFrame 即使从 NIB 加载 self ? [复制]的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Swift 中调用 Objective C UIView 的 initWithFrame
iOS:UIView子类init会调用[super init]然后调用超类中的方法,为啥会调用[subclass initWithFrame:xx]?
UIView:layoutSubviews 与 initWithFrame