我有这堂课:
class MyStoryboard: UIStoryboard {
override init() {
super.init(name: "SomeName", bundle: nil);
}
}
Swift不接受这个,因为我没有调用指定的初始化程序。但是UIStoryBoard的标题有
@availability(iOS, introduced=5.0)
class UIStoryboard : NSObject {
init(name: String, bundle storyboardBundleOrNil: NSBundle?) -> UIStoryboard
func instantiateInitialViewController() -> AnyObject
func instantiateViewControllerWithIdentifier(identifier: String) -> AnyObject!
}
此处没有convenience
个关键字。但是说它是一个方便的初始化器。然后这应该工作:
class CharacterStoryboard: UIStoryboard {
convenience override init() {
self.init(name: "SomeName", bundle: nil);
}
}
但是这会给出错误"额外的参数' name'在电话"中,好像这个初始化器甚至不存在。
我发现的唯一工作就是这样做:
class CharacterStoryboard: UIStoryboard {
convenience init(name: String, bundle storyboardBundleOrNil: NSBundle?) {
self.init(name: name, bundle: storyboardBundleOrNil)
}
convenience override init() {
self.init(name: "SomeName", bundle: nil);
}
}
这只是Swift中的一个错误,还是我错过了一些重要的东西?
更新
这段代码在运行时会创建一个无限循环,正如我之前应该发现的那样。
我认为这绝对是一个Swift错误,我应该放弃它。
答案 0 :(得分:1)
是的,这几乎肯定是一个错误。 Filing it with Apple is probably a good idea。
一些ObjC API有一个奇怪的例子,它只将工厂方法导入Swift作为“排序”初始化器;您可以看到UIStoryboard
的情况,因为init(...)
签名具有返回类型:
init(name: String, bundle storyboardBundleOrNil: NSBundle?) -> UIStoryboard
^^^^^^^^^^^^^^^
您不能在自己的Swift代码中声明带有返回类型的init
- 这只是ObjC-to-Swift导入器的工件。当你有一个像这样导入的类时,你会陷入无法编写调用指定初始值设定项的子类init
的情况下(因为就Swift知道没有指定的初始化程序而言)而你无法调用工厂方法。所以,是的,sounds like a bug。
请注意,即使修复此问题,您仍可能需要覆盖init(name:bundle:)
才能从自己的convenience init()
调用它。我希望这个类的正确Swift API有failable initializer(因为你可以指定磁盘上不存在的名称或包)。如果您要根据可用的init()
实施未失败的init?(...)
,则必须通过init!(...)
,as seen in this answer委派两次。