2016-10-10 3 views
2

Meine App verwendet Hunderte von Unterklassen einer Zeichenklasse. (Diese Unterklassen werden automatisch aus Art-Dateien generiert.)Swift 3 - Klasse Name/Typ Suche

Idealerweise würde ich gerne die Namen einiger Unterklassen laden, prüfen, ob diese Unterklassen tatsächlich verfügbar sind, und falls ja, instanziieren.

Es scheint jedoch, dass der Mangel an NSClassFromString-Style-Funktionalität in reinem Swift bedeutet, dass ich gezwungen bin, alle meine Klassennamen im Voraus zum Compiler zu deklarieren.

z.B. immer eine Klasse über eine sehr lange, mühsame switch-Anweisung:

func drawingObjectFromClassName(_ className: String) -> SomeDrawingProtocol? 
{ 
    switch className { 
     case "foo": return foo() 
     case "bar": return bar() 
     // etc. 

     default: 
      print("Warning: no class found for className: ", className) 
      return nil 
    } 
} 

Aber ich würde auch für die Existenz einer Unterklasse (zum Beispiel „foo“) überprüfen möge, ohne das Objekt zu instanziiert ist.

I könnte duplizieren, dass switch-Anweisung, dies zu tun, aber dann hätte ich zwei identische Sätze von Schlüsseln zu pflegen. Jawohl.

Eine mögliche Lösung besteht also darin, eine Nachschlagetabelle zu verwenden.

Frage: wenn ich hart-Code ein Wörterbuch mit allen meinen Unterklasse Namen wie die Tasten, welche Syntax kann ich für die Werte müssen, so dass ein abgerufenen Wert als Objekt der erforderlichen Klasse instanziiert werden kann ? Danke für jede Hilfe.

+0

Sie könnten 'foo.self' zurückgeben, um ein Klassenobjekt (vom Typ' SomeDrawingProtocol.Type') zu erhalten. – kennytm

Antwort

1
protocol P { 
    init() 
} 

extension String : P { } 

extension Int : P { } 

let types : [String : P.Type] = [ 
    "str": String.self, 
    "int": Int.self 
] 

if let type = types["int"] { 
    let object = type.init() 
    assert(object is Int) 
} 

Sie können nun alle Standard-Wörterbuch Operationen verwenden zu überprüfen, ob die Dinge vorhanden sind, werfen die Typen, die Sie jedoch herausziehen Sie wollen, usw.

ich das Protokoll im Beispiel oben definiert, um Haben Sie einen gemeinsamen Initialisierer (was wahrscheinlich in den meisten Fällen erforderlich ist), aber Sie können einfach Any.Type verwenden und den Typ bei Bedarf mit as Int.Type umwandeln.

+0

Danke Greg. Sehr geschätzt! Nachdem ich den Prototyp dem init() - Aufruf hinzugefügt und dem Automator gesagt hatte, dass er die erforderlichen init() - Aufrufe zu jeder Unterklasse hinzufügen würde, funktionierte er wie angekündigt. Prost! – Womble

+1

@Womble (nicht sicher, ob Sie das getan haben), wenn alles vom Typ 'SomeDrawingProtocol' ist, können Sie einfach' SomeDrawingProtocol.Type' als Typ für die Wörterbuchelemente verwenden, solange es einen Initialisierer erklärt, den alle Klassen implementieren. – Greg

+0

Danke Greg. Ich habe tatsächlich SomeDrawingProtocol.Type als Typ für das Wörterbuch verwendet. Es war diese init(), die mich warf ... Xcode war hilfreich (?), Um mich dazu zu bringen, den Typ (of:) ... init zu instanziieren. :) Großer Beifall. – Womble