1

在我的旧 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?还是我对这一切都错了?

4

2 回答 2

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))
}
于 2014-08-22T02:42:49.237 回答
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?
于 2014-08-22T07:31:43.343 回答