可以说我已经创建了这个协议和几个类
import UIKit protocol ControllerConstructorProtocol { class func construct() -> UIViewController? } class MyConstructor: ControllerConstructorProtocol { class func construct() -> UIViewController? { return UIViewController() } } class MyOtherConstructor: ControllerConstructorProtocol { class func construct() -> UIViewController? { return UITableViewController(style: .Grouped) } }
现在,我想声明一个数组,其中包含符合此类协议的对象类。我该如何申报?理想情况下,我希望编译器检查数组(在编译时)是否正确填充,而不是自己在运行时(运行时)检查它as。
as
这是我尝试的没有成功的方法:(
‘任何对象都没有名为’construct’的成员
var array = [ MyConstructor.self, MyOtherConstructor.self, ] var controller = array[0].construct() // << ERROR here
类型“ MyConstructor.Type”不符合协议“ ControllerConstructorProtocol”
var array: Array<ControllerConstructorProtocol> = [ MyConstructor.self, // << ERROR here MyOtherConstructor.self, ]
编辑2016/04/23 :在Swift 2.2(Xcode7.3)中,可以写@rintaro的原始想法:)
let array: Array<ControllerConstructorProtocol.Type> = [ MyConstructor.self, MyOtherConstructor.self, ] let viewController = array[0].construct()
可以像这样声明“符合协议的类的数组” Array<TheProtocol.Type>。
Array<TheProtocol.Type>
您可以:
var array: Array<ControllerConstructorProtocol.Type> = [ MyConstructor.self, MyOtherConstructor.self, ]
但…,
array[0].construct() // ^ error: accessing members of protocol type value 'ControllerConstructorProtocol.Type' is unimplemented
该项目的调用方法是“未实现”。
到目前为止,您必须将协议声明为@objc,并通过调用该方法AnyClass。此外,由于某些原因,我们不能直接施放array[0]到AnyClass,相反,我们必须把它转换为Any,然后AnyClass。
@objc
AnyClass
array[0]
Any
@objc protocol ControllerConstructorProtocol { class func construct() -> UIViewController? } var array: Array<ControllerConstructorProtocol.Type> = [ MyConstructor.self, MyOtherConstructor.self, ] let vc = (array[0] as Any as AnyClass).construct()
注意:投放问题已在Swift 1.2 / Xcode 6.3中修复。但是“未实现”是“未实现” :(
只是随机的想法:
这取决于您的实际用例,但是在这种特殊情况下,()-> UIViewController?闭包数组就足够了:
()-> UIViewController?
var array: [() -> UIViewController?] = [ MyConstructor.construct, MyOtherConstructor.construct, ] let vc = array[0]()
如果您有几种方法,则可能要使用协议的类型擦除的包装器。
protocol ControllerConstructorProtocol { class func construct() -> UIViewController? class func whoami() -> String } struct ControllerConstructorWrapper { private let _construct: () -> UIViewController? private let _whoami: () -> String init<T: ControllerConstructorProtocol>(_ t:T.Type) { _construct = { t.construct() } _whoami = { t.whoami() } } func construct() -> UIViewController? { return _construct() } func whoami() -> String { return _whoami() } } var array: [ControllerConstructorWrapper] = [ ControllerConstructorWrapper(MyConstructor), ControllerConstructorWrapper(MyOtherConstructor), ] let who = array[0].whoami() let vc = array[0].construct()