2017-01-05 3 views
3

Instanziierungsanwendung habe ich eine verschachtelte Klasse wie folgt definiert:eine verschachtelte Klasse mit NSClassFromString in schnellen

@objc class A { 
    @objc class B{ 

    } 
} 

und ich brauche A.B mit NSClassFromString instanziiert. Ich konnte es für die einfache Klasse A tun, aber wenn ich an den NSClassFromString Parameter die .B Zeichenfolge anschließe, gibt es einfach null zurück.

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

Ich nehme an, dass ... da geschachtelte Klasse in Objective-c die NSClassFromString nicht verfügbar ist, funktioniert einfach nicht für verschachtelte Klassen in diesem Fall gibt es eine andere Art und Weise eine verschachtelte Klasse aus einer Zeichenfolge zu initialisieren?

// EDIT

ist gespannt, wie die inverse Funktion NSStringFromClass kehrt anderes Format als für eine Standard-Klasse und eine verschachtelte Klasse ausgeführt:

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

Wie Sie das Format sehen völlig anders. Was ist das _TtCC15? Warum zum "." wurde entfernt? Ich nehme an, dass das Weitergeben der Klasse in diesem Format an NSClassFromString funktionieren sollte.

+1

Versuchen Sie, Klasse B als @objc wie folgt zu markieren: '@objc Klasse B {}'. –

+0

Schon versucht ... Ich update die Antwort aber, danke für das Aufzeigen! – MatterGoal

+0

Versuchen Sie, 'class B' mit' public' zu versehen. Wie diese @objc öffentliche Klasse B – NSDmitry

Antwort

2

Ich finde, dass folgende Arbeiten auf einem Spielplatz (Xcode 8.2/Swift 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" 

Die oddball Klasse "name" string ist, weil die ObjC Laufzeit nicht verschachtelte Klassen (oder andere Arten versteht von Typen, die Swift definieren kann, aber ObjC kann nicht - in Swift selbst sind solche verstümmelten Namen, wie Typen, Funktionen und solche eindeutig definiert werden. (Zum Beispiel ist der Name Mangeln auch, wie Funktion Überlastung Werke: func foo() und func foo(num: Int) -> Bool haben unterschiedliche verstümmelten Namen intern.)

Die überbrückende Maschinen noch dynamisch gemacht werden kann, um eine Klasse seine richtig verstümmelten Swift Namen gegeben zu beheben, aber Swift Namen Mangeln ist ein Implementierungsdetail und kann sich ändern. (Wenigstens bis Swift 4 den ABI sperrt.) So ist es sicher, das Ergebnis von NSStringFromClass innerhalb desselben Programms an NSClassFromString zu übergeben, aber nicht sicher (z. B.) einen verstümmelten Namen einmal im Test aufzuzeichnen, diesen verstümmelten Namen als String zu versenden Literal oder Ressource in Ihrer App, und erwarten, dass es später mit NSClassFromString funktioniert.

Stattdessen, wenn Sie Ihre verschachtelte Klasse wollen (oder jede andere Swift definierte Klasse) einen zuverlässig bekannten Namen in der ObjC Laufzeit für den Einsatz haben, gibt ihnen ein @objc(name) (wie in the docs beschrieben):

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

(Beachten Sie, dass dieses Snippet nicht von selbst ausgeführt wird - die Klasse A.B muss mindestens einmal irgendwo in Ihrem Prozess referenziert werden, um bei der ObjC-Laufzeit registriert zu sein. Dies könnte so einfach sein wie let t = A.B.self irgendwo in Ihrer App Startcode.)

+0

Der Name ObjC hat den Trick gemacht! Über den Rest Ihrer Antwort, großartige Erklärung! – MatterGoal

Verwandte Themen