2016-06-27 4 views
1

Вот простой протокол:Swift протокол определяет инициализации, который не работает на UIViewController

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?

EDIT

Это, кажется, работает, когда сдерживающие расширение до базового класса (NSObject или любого Swift класса, который не наследует от чего-либо), но не тогда, когда сдерживающие расширение для дочернего класса.

+0

Что именно вы tryign достичь, так или иначе? Это не имеет смысла. Вы расширяете 'StringsViewController' ... это не подкласс' UIViewController'? – Alexander

+0

не против примера, если вы попробуете с расширением StringsViewController, где Self: NSObject', вместо этого он работает. В этом случае с UIViewController (и, я думаю, с NSCoding) что-то не так. И это не однотипное требование;) – greg3z

ответ

0

UIViewController не имеет такого инициатора, поскольку вы не реализовали протокол StringsViewController. Вы не сможете реализовать этот протокол для UIViewController, потому что вы не можете объявить инициализатор проекта в расширение. С другой стороны, вам нужен назначенный инициализатор, чтобы соответствовать требованию init протокола.

+0

Я не уверен, что понимаю, что вы говорите. Код в 'extension StringsViewController, где Self: UIViewController' будет доступен для подклассов UIViewController, которые соответствуют протоколу' StringsViewController'. Поэтому они должны предоставить 'init (строки: [String]) ... как я сказал в другом комментарии, замените UIViewController на NSObject, и он работает ... – greg3z

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

У вас может быть точка там ... Она работает при использовании базовый класс, NSObject в моем случае, A в вашем случае, но не при использовании подклассов. Я попытался с другими подклассами, и это тоже не удалось. Имя моего протокола было плохо выбрано, я изменил его. – greg3z

Смежные вопросы