如何从运行时创建的字符串中实例化Swift对象?

时间:2015-02-20 14:01:19

标签: objective-c cocoa swift

在objectiveC库中有许多基于其类的名称(字符串表示)实例化对象的情况。

我与以下工作代码非常接近:

class Person{
    var age:Int = 1

    //somehow this is critical
    required init () {
    }
}

class Dog{
    var color:String = "Blue"

    //somehow this is critical
    required init () {
    }
}

/*
The basics
*/

let X = Person.self
var p1 = X()
p1.age = 5
println(p1.age)


/*
Instantiate from a String
*/
var hash1 = ["person":Person.self]

if let t = hash1["person"]{
    let p2 = t()
    p2.age = 8
    println(p2.age)
}

字典的最后一个片段接近真实世界的实现应该是什么样子,除了我们需要能够将多个Type放入字典中;辨别两者并从结果中实例化。类似于以下非工作代码:

var hash2 = ["dog":Dog.self, "person":Person.self] // needed for real-world usage
if let t2 = hash2["person"]{ // warning
    let p3 = t2()   //error
    p3.age = 11
    println(p3.age)
}

1 个答案:

答案 0 :(得分:5)

请参阅,Swift是一种非常类型安全的语言。所以当你弄乱任何不同的类型时,最好对编译器说什么我们会搞乱。 所以hash2行看起来像这样:

var hash2: [String: Any] = ["dog": Dog.self, "person": Person.self]'

这里你要说的是,该字典将使用字符串的键类型和任意类型的值(AnyObject来自Obj-c中的NSObject,这里是任何类型,因为Dog.self和Person.self不是来自obj -c和不一样的类型)

然后,在展开时,您需要说出它将是什么类型,所以下一个代码将是这样的:

if let t2 = hash2["person"] as? Person.Type {
    let p3 = t2() 
    p3.age = 11
    println(p3.age)
}

在这里,我不仅尝试从字典中获取密钥,而且还尝试将其转换为Person.Type类型。当我提到字典正在减速时,贝塞尔值可以是Any类型,我需要将其转换为特定类型才能使用age属性和()操作


UPD:

Swift是类型安全的,因此如果myObj.age不是来自myObj并且没有特定类型,则您无法NSObject。在你的例子中,Dog和Person没有任何相似之处,因此将它们组合在一起是不合逻辑的。 如果它有相似之处,那么你可以创建协议并投射到它。示例如下:

protocol Aged {
    var age: Int {get set}
    init()
}

class Person: Aged {
    var age: Int = 1

    //somehow this is critical
    required init () {
    }
}

class Dog: Aged {
    var age: Int =  5
    var color:String = "Blue"

    //somehow this is critical
    required init () {
    }
}

var hash2: [String: Any] = ["dog":Dog.self, "person":Person.self] // needed for real-world usage
if let t2 = hash2["person"] as? Aged.Type { 
    let p3 = t2() 
    println(p3.age)
}