Ios 自我初始化。。与超级初始化。。。在子类中
我有一个Ios 自我初始化。。与超级初始化。。。在子类中,ios,objective-c,init,super,Ios,Objective C,Init,Super,我有一个UIViewContoller子类baseviewcontroller。它有一个名为-initWithStyle:的方法。如果我将该类子类化为subsaviewcontoller, -[subsaviewcontroller init]应该是什么样子 我的代码: - (id)init { self = [self initWithStyle:kGreenStyle]; if (self) { // stuff } return self;
UIViewContoller
子类baseviewcontroller
。它有一个名为-initWithStyle:
的方法。如果我将该类子类化为subsaviewcontoller
,
-[subsaviewcontroller init]
应该是什么样子
我的代码:
- (id)init
{
self = [self initWithStyle:kGreenStyle];
if (self) {
// stuff
}
return self;
}
在subsaviewcontroller
中,我没有initWithStyle:
我的应用程序在上面的
-init
中随机崩溃,我检查了属于BaseViewController
子类的其他视图控制器,它们使用self=[super-initWithStyle:kGreenStyle]
,并正常工作。解释是什么?你应该使用super而不是self:
- (id)init
{
self = [super initWithStyle:kGreenStyle];
if (self) {
}
return self;
}
如果您这样做,您将强制父类执行它应该执行的所有初始化。如果您想在init方法中仅在子类中执行某些操作,请将其添加到此处:
- (id)init
{
self = [super initWithStyle:kGreenStyle];
if (self) {
// do some stuff you need to do in subclass initialisation
// for example init variable specific just for that class (not parent class)
}
return self;
}
UIViewController
有两个指定的初始值设定项:
- (id)initWithNibName:(NSString *)nibName bundle:(NSBundle *)nibBundle;
及
当使用Interface Builder定义具有资源(即nib文件或序列)的视图控制器时,将调用第二种形式。手动创建视图控制器时,可以使用第一个表单
您可以按如下方式覆盖这些初始值设定项:
// Designated initializer
- (id)initWithNibName:(NSString *)nibName bundle:(NSBundle *)nibBundle
{
self = [super initWithNibName:nibName bundle:nibBundle];
if (self) {
; // your initialization
}
return self;
}
// Designated initializer
- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
; // your initialization
}
return self;
}
注意:从资源创建时,不会调用方法init
。当您自己调用init
时,它最终将使用nil
参数调用initWithNibName:bundle:
另见:参考:
您的问题的另一种可能的解决方案:
提供初始化自定义视图控制器的方法的一种方法是使用“便利类方法”。在这种情况下,您不需要重写指定的初始值设定项,而是在子类中提供属性
便利类方法可能如下所示:
// MyViewController
+ (instancetype) myViewControllerWithStyle:(Style)style
{
// Possibly get the bundle and the nib name (or leave it nil)
...
// Invoke a designated initializer with suitable parameters:
MyViewController* viewController = [[MyViewController alloc] initWithName:nibName
bundle:bundle];
viewController.style = style;
return viewController;
}
这是Greg和CouchDeveloper答案的综合。 但实际上,这是对格雷格答案的辩护 首先,是的,了解指定的初始值设定者。它们很重要,而且是CouchDeveloper 强调这一点是正确的 其次,没有任何东西可以阻止
UIViewController
的子类
完全不同的指定初始值设定者(最好是一个)由您自己选择。
如果在Interface Builder外部创建UIViewController
s,
正如OP可能正在做的那样,-initWithNibName:Bundle:
而且-initWithCoder:
变得很愚蠢
苹果说:
定义子类时,必须能够识别超类的指定初始值设定项,并通过发送给super的消息在子类的指定初始值设定项中调用它。您还必须确保以某种方式覆盖继承的初始值设定项
鉴于此,OP的BaseViewController
可能是这样的:
const NSUInteger kDefaultStyle = 0; // just to have something to use
@implementation BaseViewContoller
// No longer valid for *this* class.
// Should have one for -initWithCoder: too, but elided for this example.
- (instancetype)initWithNibName:(NSString *)nibNameOrNil
bundle:(NSBundle *)nibBundleOrNil
{
[self doesNotRecognizeSelector:_cmd];
return nil;
}
// New designated initializer for *this* class.
// This should call the superclass's designated initializer.
- (instancetype)initWithStyle:(NSUInteger)style
{
// use the designated initializer of the superclass to init
if ((self = [super initWithNibName:nil bundle:nil])) {
// stuff
}
return self;
}
// in *other* initializers, you *should* call *your* class's
// designated initializer.
- (instancetype)init
{
return [self initWithStyle:kDefaultStyle];
}
@end
鉴于此,我认为CouchDeveloper的“这是错误的”在评论中呼喊
格雷格的答案本身就是错误的。这是因为:
是不可见的,所以我们不可能知道它指定的初始值设定项是什么,不管它的超类是什么BaseViewController
- OP已给出所有指示,
是指定的初始值设定项-[BaseViewController initWithStyle:
- OP完全可以自由地将
声明为指定的初始值设定项,只要他遵守规则[subsaviewcontroller init]
- 假设这些不是你原来的文章中的拼写错误,你应该始终将
类名的第一个字母<代码>基本视图控制器,而不是
。 你可以逆水行舟,成语是当你 变成一个十足的坏蛋;到那时,我敢打赌你不会想的基本视图控制器
nil
作为nibName调用init
时,则nibName
属性设置为nil。在这种情况下,运行时要么使用您在loadView
中创建的视图,要么根据中描述的启发式搜索nib文件。这就是为什么如果您有一个MyViewController
和一个MyViewController.xib
可以使用普通init
,它将使用关联的nib文件。@Abizern谢谢Abizern,这是有用的信息。因此,为了创建自定义视图控制器,最好创建一个“便利类方法”,它完全封装了这些细节(nib名称和bundle参数)。请参阅我的答案以了解更多细节。@Greg我想道歉:我之前关于这个答案是错误的声明过于仓促。事实上,如果基类正确实现,如@claybridges所示,即initWithStyle:
是一个合适的指定初始值设定项,它将工作。
const NSUInteger kDefaultStyle = 0; // just to have something to use
@implementation BaseViewContoller
// No longer valid for *this* class.
// Should have one for -initWithCoder: too, but elided for this example.
- (instancetype)initWithNibName:(NSString *)nibNameOrNil
bundle:(NSBundle *)nibBundleOrNil
{
[self doesNotRecognizeSelector:_cmd];
return nil;
}
// New designated initializer for *this* class.
// This should call the superclass's designated initializer.
- (instancetype)initWithStyle:(NSUInteger)style
{
// use the designated initializer of the superclass to init
if ((self = [super initWithNibName:nil bundle:nil])) {
// stuff
}
return self;
}
// in *other* initializers, you *should* call *your* class's
// designated initializer.
- (instancetype)init
{
return [self initWithStyle:kDefaultStyle];
}
@end