ひとしれずひっそり

主にソフトに関することをメモしていきます。過程をそのまま書いていたりするので間違いが含まれます。鵜呑みしない様に。

オブジェクトからクラス名を取得するやクラス名からオブジェクトを生成

現時点でSwift流のやり方は分かってない。
従来からあるNSClassFromString()、NSStringFromClass()を使う。

オブジェクトからクラス名を取得

class A {}
NSStringFromClass(A.self) // -> "__lldb_expr_13.A"

空間名(という表現でいい?)がAの前につく様だ。


@objc(A)
class A: NSObject {}
NSStringFromClass(A.self) // -> "A"

NSObjectから継承し@objc(A)を付けることで"A"として得られる。


実はNSStringFromClass()を使わなくても得られる。
NSObjectも関係ない。
Swift流ということでいい?

class A {}
let a = A()
String(describing: type(of: a))  // -> "A"

クラス名からオブジェクトを生成

@objc(A)
class A: NSObject {
    required override init() {}
}

if let t = NSClassFromString("A") as? A.Type {
    _ = t.init() // -> Aのオブジェクト
}
  • 前に書いた様にrequiredを付けたinit()メソッドが必要。 katsuyoshi.hatenadiary.com
  • NSClassFromString()で取得できるのはNSObjectを継承したクラスじゃないといけない。
  • そのメソッドを得るには@objc()でobjcのメソッドを扱うことを明示しないといけない。
  • NSClassFromString("A") as? A.TypeとクラスAであることを付加しないとinit()を受け付けてくれない。
    Aの派生クラスのみ対象とできる。
@objc(A)
class A: NSObject {
    required override init() {
        super.init()
        debugPrint(String(describing: Self.self))
    }
}


@objc(B)
class B: A {
    
}

if let t = NSClassFromString("A") as? A.Type {
    _ = t.init() // -> Aのオブジェクト
}
if let t = NSClassFromString("B") as? A.Type {
    _ = t.init() // -> Bのオブジェクト
}

とここまで、正解かどうかは置いておいて、現時点での認識。