2017-01-05 126 views
3

實例化使用NSClassFromString嵌套類我有這樣定義一個嵌套類:在迅速

@objc class A { 
    @objc class B{ 

    } 
} 

,我需要使用NSClassFromString實例A.B。我能夠爲簡單的類A做到這一點,但是當我附加到NSClassFromString參數.B字符串時,它只返回nil。

NSClassFromString("\(appName).A") // works... 
NSClassFromString("\(appName).A.B") //doesn't work. 

我想,既然嵌套類是不可用Objective-C中的NSClassFromString只是沒有嵌套類工作......在這種情況下,有另一種方式從字符串初始化一個嵌套類?

//編輯

是好奇如何反函數返回NSStringFromClass不同格式時的標準類和嵌套類執行:

"myApp.A" <---- STANDARD CLASS (A) 
"_TtCC15myApp13A6B" <----- NESTED CLASS (A.B) 

正如你所看到的格式是完全不同的。那是什麼_TtCC15?爲什麼 」。」已被刪除?我認爲應該以這種格式傳遞給NSClassFromString

+1

嘗試將類B標記爲@objc,如下所示:'@objc class B {}'。 –

+0

已經嘗試過......我更新了答案,謝謝指出! – MatterGoal

+0

嘗試用'public'關鍵字給'class B'加前綴。像這樣'@objc public class B' – NSDmitry

回答

2

我發現,在操場下面的工作(的Xcode 8.2 /斯威夫特3):

// inheriting NSObject is required for `@objc`, at which point `@objc` is optional 
class A: NSObject { 
    class B: NSObject { 
     override var description: String { return "foo" } 
    } 
} 

let str = NSStringFromClass(A.B.self) 
guard let anyClass = NSClassFromString(str) 
    else { fatalError("no class") } 
// cast to a type that defines `init()` so we can instantiate 
guard let nsClass = anyClass as? NSObject.Type 
    else { fatalError("class isn't NSObject") } 
// call `.init()`, not `nsClass()`; constructor syntax is for static types only 
let instance = nsClass.init() 
print(instance) // -> "foo" 

的古怪類別「姓名」字符串,是因爲ObjC運行時不明白的嵌套類(或其他種類Swift可以定義的類型,但ObjC不能) - 在Swift本身中,這樣的破壞名稱是類型,函數等的唯一定義。 (例如,名稱重整也重載函數是如何工作的:func foo()func foo(num: Int) -> Bool有內部不同重整的名稱。)

橋接機器仍可以動態地解決一類給予其適當錯位斯威夫特的名字,但斯威夫特名稱重整是一個實現細節,可能會更改。 (至少在Swift 4鎖定ABI之前。)因此,在同一個程序中將NSStringFromClass的結果傳遞給NSClassFromString是安全的,但不安全(例如)在測試中記錄一個錯位的名稱,將該錯位的名稱作爲字符串文字或資源在您的應用程序中,並期望它在稍後使用NSClassFromString

相反,如果你希望你的嵌套類(或任何其他雨燕定義的類),以在ObjC運行時使用有可靠的響亮的名字,給它一個@objc(name)(如the docs描述):

@objc class A: NSObject { 
    @objc(A_B) class B: NSObject { /*...*/ } 
} 
guard let anyClass = NSClassFromString("A_B") 
    else { fatalError("no class") } 

(請注意,這段代碼不會自行運行 - 類A.B必須在您的進程中至少一次引用,以便在ObjC運行時註冊,這可能與將let t = A.B.self放在應用程序的某處啓動代碼。)

+0

使用ObjC名字做了詭計!關於你的答案的其餘部分,很好的解釋! – MatterGoal