2015-02-06 82 views
3

UIViewController类定义了一个单一指定初始化,init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?)和不便利初始化器,但是,它是可能写入的代码下面的行,并且具有其编译(6.1.1的Xcode)UIViewController如何在Swift中设置默认的非参数初始值设定项?

let vc = UIViewController()

这是如何可能?

据雨燕的书,这里有初始化继承的规则

规则1如果你的子类没有定义任何指定的初始化程序,它 自动继承其所有超类指定初始化的。

规则2如果你的子类,要么初始化通过继承他们为每 规则1提供其所有 超指定的一个实现,或通过提供一个自定义实现其 定义然后,它会自动继承所有的一部分

摘录自:苹果公司“The Swift Programming Language。”iBooks。 https://itun.es/us/jEUH0.l

因此UIViewController不能继承其祖先init()方法超类NSObject,那么哪里初始化从何而来?

在另一个说明中,因为每个swift类必须最终调用它的指定初始化方法,那么这是不是意味着initWithCoder:也最终会调用init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?)?但是,实际情况似乎并非如此。

+1

它有一个'initWithCoder:'方法,因为它符合'NSCoding',它需要它。不知道为什么它有一个默认的初始化器...因为它是一个Objective-C类而不是Swift类,所以不需要遵循Swift继承的规则,所以它不必调用指定的初始化器。如果你在Swift中重写它,你可能不得不这样做。迅速尝试做的很大一部分是澄清许多这些奥术规则的例外。 – 2015-02-06 18:14:08

回答

3

Swift书中的规则适用于在Swift中定义的类。 UIViewController是从ObjC导入的一个类,因此它的行为受ObjC规则(或缺乏)的支配。

在ObjC,指定初始化链模式是你应该 DO(不像斯威夫特在编译器强制它的可以做的唯一的事情)。如果您调用继承的初始化程序而不是指定的初始化程序,您将返回一个实例...但不能保证所述实例处于合理的状态。 (实际上,你几乎可以肯定它不会这样。)ObjC类的作者有时会通过实现你不应该调用的初始化方法并让它们抛出异常来实践防御性编码,但这似乎不是这里的情况。

这个特例可能是某种错误 - it wouldn't be a bad idea to file one with Apple。 Swift应该在从导入的ObjC API创建对象时执行初始化器规则(在这种情况下,UIViewController需要在ObjC中声明其指定初始值设定项,NS_DESIGNATED_INITIALIZER),或者应该执行UIViewController以防止不正确的初始化。 (尽管有可能会有兼容性副作用来“修复”其中的任何一种。)

1

高于init功能注释块包含下列文字:

/* 
    The designated initializer. If you subclass UIViewController, you must call the super implementation of this 
    method, even if you aren't using a NIB. (As a convenience, the default init method will do this for you, 
    and specify nil for both of this methods arguments.) ... 
*/ 

这是我的理解是,因为这是一个Objective-C类,允许隐式继承的方法。如果你在swift中创建这个类的子类,你将无法访问super.init()。如果您在Objective-C代码中创建子类而不实现您自己的-[ init],则您的能够使用()构建您的子类。

因为您的项目会通过您所调用的类落入Objective-C域,因此可以找到选择器。 Objective-C类的swift子类只能遵循快速继承规则。