在我的旧Obj-C代码中,我可以声明一个字典,其值是其他类的Class
类型
NSMutableDictionary *Methods = [[NSMutableDictionary alloc] init];
[Methods setObject:[AuthReturnValue class] forKey:@"Authenticate"];
[Methods setObject:[MyOptions class] forKey:@"GetOptions"];
稍后,根据密钥,我可以将Class
分配给另一个变量
(在标题中)
Class returnType;
(在实施中):
returnType = (Class)[Methods objectForKey:methodName];
然后我可以使用这个Class
变量声明一个相同类型的新变量(在这种情况下,它使用JSONModel并从其他地方用NSDictionary
初始化它)
id<NSObject> result;
result = [[returnType alloc] initWithDictionary:(NSDictionary *)responseObject error:NULL];
这非常方便,因为JSONModel实现了initWithDictionary
,这意味着我可以通过这种方式提取Class
,而无需实例化特定类型。
我无法弄清楚如何在Swift中执行此操作。
例如,这不起作用:
var result: self.returnType.self()
var result: AnyClass = self.returnType.self
还有几十个变种。
如何将Swift中的变量声明为class
对象中定义的AnyClass
?或者我是不是错了?
答案 0 :(得分:5)
据我所知,你无法实例化AnyClass
。你必须将它转变为更具体的类型。此外,要使用其元类型实例化的类型必须具有必需的初始化。如果我理解了您的示例,AuthReturnValue
和MyOptions
都是JSONModel
的子类,其init(responseObject:error:)
初始值。然后必须要求每个子类都使用该初始化器。
class JSONModel {
required init(responseObject: NSDictionary, error: NSError?) {
}
}
class AuthReturnValue : JSONModel {
required init(responseObject: NSDictionary, error: NSError?) {
super.init(responseObject: responseObject, error: error)
}
}
class MyOptions : JSONModel {
required init(responseObject: NSDictionary, error: NSError?) {
super.init(responseObject: responseObject, error: error)
}
}
现在你可以这样做:
var methods = [String : JSONModel.Type]()
methods["Authenticate"] = AuthReturnValue.self
methods["GetOptions"] = MyOptions.self
if let returnType = methods["Authenticate"] {
let result = returnType(responseObject: NSDictionary(), error: nil)
}
<强>更新强>
上面的代码适用于本机Swift类,但如果与Objective-C类的子类一起使用,则会崩溃(Xcode6-Beta6)。解决方法是在使用之前将元类型值存储在[String : Any.Type]
字典中并向下转发。以下示例显示如何使用NSOperation
的子类执行此操作。
class SomeOperation : NSOperation {
}
var dictionary = [String : Any.Type]()
dictionary["some operation"] = SomeOperation.self
if let aClass = dictionary["some operation"] as? NSOperation.Type {
// Any initializer available in the superclass can be used for
// creating instances. The compiler will not perform any checks,
// as it does with native Swift classes, so we must ensure that subclasses
// actually implement those initializers, either by automatically inheriting
// or overriding.
let test = aClass()
println(NSStringFromClass(test.dynamicType))
}
答案 1 :(得分:0)
我在一个小的依赖注入框架中实现了类似的东西,最后我发现实现它的最好方法是存储一个实例化对象的闭包。
这是我实现实例化器类的方法:
typealias Constructor = (responseObject: NSDictionary, error: NSError?) -> AnyObject
class Instantiator {
private var instantiators = [String : Constructor]()
func bindKey<T : AnyObject>(key: String, withType type:T.Type, toInitializer initializer: Constructor) {
self.instantiators[key] = initializer
}
func instanceForKey(key: String, responseObject: NSDictionary, error: NSError?) -> AnyObject? {
if let instantiator = self.instantiators[key] {
return instantiator(responseObject: responseObject, error: error)
}
return .None
}
}
然后我会用它:
class MyClass {
let x = "Test"
init(responseObject: NSDictionary, error: NSError?) {}
}
let instantiator = Instantiator()
instantiator.bindKey("GetOptions", withType: MyClass.self) { (responseObject: NSDictionary, error: NSError?) -> MyClass in
return MyClass(responseObject: responseObject, error: error)
}
let x: MyClass! = instantiator.instanceForKey("GetOptions", responseObject: NSDictionary(), error: nil) as MyClass?