酢ろぐ!

カレーが嫌いなスマートフォンアプリプログラマのブログ。

Swiftで文字列のクラス名からインスタンスを動的に生成させる

文字列からインスタンスを生成する方法として、Objective-Cでは「文字列のクラス名からインスタンスを動的に生成させる - iOSアプリ開発の逆引き辞典」で紹介しているようなコードを書くことで文字列のクラス名称からインスタンスを動的に生成させることができました。

Swiftとして文字列からインスタンスを動的に生成する方法は見つけることができませんでした。Objective-Cの力を借りる方法しかわかりませんでした。

文字列のクラス名からインスタンスを生成する

以下のようなDogクラスがあるとしましょう。名前は「まろにー」です。

@objc(Dog)
class Dog : NSObject {
    let name: String
    
    override init() {
        self.name = "まろにー"
    }
}

Objective-Cの時と同様にNSClassFromString関数を使用します。

// 文字列から型情報を取得する
let obj = NSClassFromString("Dog") as! NSObject.Type

// Dogインスタンスを生成する
let dog = obj() as! Dog

// 出力
println("私は犬である。名前は\(dog.name)")

文字列のクラス名からコンストラクタ引数付きでインスタンスを生成する

前述した方法では引数付きのコンストラクタを呼び出すことができず、デフォルトコンストラクタが呼ばれることになってしまいます。

今度は以下のようなPersonクラスのインスタンスを生成させてみましょう。

@objc(Person)
class Person : NSObject {
    let age: Int
    let name: String
    
    required init(age: Int, name: String) {
        self.age = age
        self.name = name
    }
}

先ほどのようにNSClassFromString関数を使用して、NSObject.Type型のオブジェクトを取得します。

 // 文字列から型情報を取得する
let obj: NSObject.Type = NSClassFromString("Person") as! NSObject.Type
if !(obj is Person.Type) {
    // 型情報が取得出来なかった場合は処理しない
    return
}
        
// NSObject.TypeをPerson.Typeにキャストする
let type = obj as! Person.Type
        
// インスタンスを生成する
let person = type(age: 17, name: "さくさん")

// 出力
println("\(person.name)\(person.age)歳でしゅ")