[英]Swift protocol defines an init that doesn't work for UIViewController
Here is a simple protocol: 这是一个简单的协议:
protocol StringsInitiable {
init(strings: [String])
}
Trying to use the initializer in an extension works when constraint to NSObject... 当对NSObject进行约束时,尝试在扩展中使用初始化程序。
extension StringsInitiable where Self: NSObject {
func test() {
let _ = Self(strings: [])
}
}
...but not when constraint to UIViewController. ...但不限于UIViewController。 It then complains that the initializer should be labeled 'coder', referring to the mandatory initializer from NSCoding. 然后,它抱怨初始化程序应标记为“编码器”,这是指NSCoding中的强制性初始化程序。
extension StringsInitiable where Self: UIViewController {
func test() {
let _ = Self(strings: []) // error label 'strings:' expected 'coder:'
}
}
Is there a way to use the initializer declared in the protocol even when being a UIViewController subclass? 即使是UIViewController子类,有没有办法使用协议中声明的初始化程序?
EDIT 编辑
It seems to be working when constraining the extension to a base class (NSObject or any Swift class that doesn't inherit from anything) but not when constraining the extension to a child class. 当将扩展限制为基类(NSObject或任何不继承自任何东西的Swift类)时,这似乎是可行的,但当将扩展限制为子类时,则无效。
I'm not entirely convinced, but this smells like a bug. 我并不完全相信,但这闻起来像个虫子。 Have a look at this example which doesn't compile: 看一下这个没有编译的例子:
protocol P {
init(n: Int)
}
class A {}
class B : A {}
extension P where Self : B {
func f() -> Self {
return Self(n: 3) // Error
}
}
But this compiles: 但这会编译:
extension P where Self : A {
func f() -> Self {
return Self(n: 3)
}
}
Probably you don't want a protocol for that anyways, since you even named it StringsViewController
. 无论如何,您可能都不想要该协议,因为您甚至将其命名为StringsViewController
。 You should probably subclass UIViewController
: 您可能应该子类化UIViewController
:
class StringsViewController : UIViewController {
convenience init(strings: [String]) {
self.init()
}
}
extension StringsViewController {
func test() {
let _ = StringsViewController(strings: [])
}
}
Or if you really want a protocol you can do something like this: 或者,如果您真的想要一个协议,则可以执行以下操作:
protocol HasView {
var view : UIView! { get }
}
protocol StringsInitable {
init(strings: [String])
}
extension UIViewController : HasView {}
extension HasView where Self : StringsInitable {
func test() {
let n = Self(strings: [])
print(n.view)
}
}
UIViewController doesn't have such an initialiser, because you haven't implemented the StringsViewController protocol. UIViewController没有这样的初始化程序,因为您尚未实现StringsViewController协议。 You would not be able to implement this protocol for UIViewController, because you cannot declare a designed initialiser into an extension. 您将无法为UIViewController实现此协议,因为您无法在扩展中声明设计的初始化程序。 On the other hand you need a designated initialiser in order to conform to a init requirement of a protocol. 另一方面,您需要指定的初始化程序才能符合协议的初始化要求。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.