Swift协议定义了一个不适用于UIViewController的init

时间:2016-06-27 16:40:42

标签: ios swift uiviewcontroller protocols

这是一个简单的协议:

protocol StringsInitiable {
    init(strings: [String])
}

在对NSObject约束时,尝试在扩展中使用初始化程序...

extension StringsInitiable where Self: NSObject {
    func test() {
        let _ = Self(strings: [])
    }
}

...但不是在对UIViewController的约束时。然后它抱怨初始化程序应标记为“编码器”,参考NSCoding的强制初始化程序。

extension StringsInitiable where Self: UIViewController {
    func test() {
        let _ = Self(strings: []) // error label 'strings:' expected 'coder:'
    }
}

有没有办法使用协议中声明的初始化程序,即使是UIViewController子类?

修改

在将扩展限制为基类(NSObject或任何不从任何东西继承的Swift类)时似乎正在工作,但在将扩展限制为子类时却没有。

2 个答案:

答案 0 :(得分:2)

我并不完全相信,但这闻起来像个臭虫。看看这个没有编译的例子:

protocol P {
    init(n: Int)
}

class A {}

class B : A {}

extension P where Self : B {
    func f() -> Self {
        return Self(n: 3) // Error
    }
}

但这会编译:

extension P where Self : A {
    func f() -> Self {
        return Self(n: 3)
    }
}

可能你不想要一个协议,因为你甚至将其命名为StringsViewController。您可能应该继承UIViewController

class StringsViewController : UIViewController {
    convenience init(strings: [String]) {
        self.init()
    }
}

extension StringsViewController {
    func test() {
        let _ = StringsViewController(strings: [])
    }
}

或者如果你真的想要一个协议,你可以这样做:

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)
    }
}

答案 1 :(得分:0)

UIViewController没有这样的初始化器,因为你还没有实现StringsViewController协议。您将无法为UIViewController实现此协议,因为您无法将设计的初始化程序声明为扩展。另一方面,您需要一个指定的初始化程序,以符合协议的初始化要求。