2017-10-02 3 views
7

Wie erhalten Sie einen Zeichenfolgenwert von Swift 4 smart keypaths Syntax (z. B. \Foo.bar)? An dieser Stelle bin ich auf jeden Fall neugierig, egal, ob es kompliziert ist.Die Zeichenfolge von Swift 4 erhalten Syntax für den neuen Schlüsselpfad?

Ich mag die Idee der Typinformationen mit Smart-Key-Pfad zugeordnet werden. Aber nicht alle APIs und Drittanbieter sind noch da.

Es gibt eine alte Methode, die Zeichenfolge für den Eigenschaftsnamen mit der Kompilierungsvalidierung von #keyPath() abzurufen. Mit Swift 4 #keyPath() zu verwenden, müssen Sie eine Eigenschaft als @objc deklarieren, was ich lieber vermeiden würde.

Antwort

5

Für Objective-C-Eigenschaften in Objective-C-Klassen können Sie die _kvcKeyPathString property verwenden, um es zu erhalten.

Swift-Schlüsselpfade dürfen jedoch keine String-Entsprechungen haben. Es ist ein erklärtes Ziel der Swift-Schlüsselpfade, dass keine Feldnamen in der ausführbaren Datei enthalten sein müssen. Es ist möglich, dass ein Schlüsselpfad als eine Abfolge von Offsets von Feldern dargestellt werden kann, die abgerufen werden sollen, oder von Schließungen, um ein Objekt anzurufen.

Dies steht natürlich in direktem Widerspruch zu Ihrem eigenen Ziel zu vermeiden, Eigenschaften @objc zu deklarieren. Ich glaube, dass es keine eingebaute Möglichkeit gibt, das zu tun, was Sie tun möchten.

+1

Schöner Fang! Ich habe hier einen schnellen Test gemacht, und leider sieht es so aus, als ob die oben erwähnte '_kvcKeyPathString'-Eigenschaft * nur * Nicht-Nil-Werte für '@ objc' exposed-Eigenschaften zurückgibt. Zum Beispiel, beide 'Name' und' email' Schlüsselwege, in meiner Antwort oben, zurückgegeben in 'nil'. –

+0

Hinweis von einer verwandten Frage: >> * Aber wenn Sie das '@ objc' Attribut zur Eigenschaft hinzufügen, dann hat' _kvcKeyPathString' tatsächlich einen Wert anstatt immer 'nil'. * << https: // stackoverflow.com/questions/46143292/is-it-possible-to-get-the-kvc-string-from-swift-4-keypath – pkamb

8

Kurze Antwort: Sie können nicht. Die KeyPath Abstraktion wurde entworfen, um eine möglicherweise verschachtelte Eigenschaft Schlüsselpfad von einem bestimmten Stammtyp einzukapseln. Daher ist der Export eines einzelnen Werts String im allgemeinen Fall möglicherweise nicht sinnvoll.

Zum Beispiel sollte der hypothetisch exportierte String als eine Eigenschaft des Root-Typs oder ein Mitglied einer seiner Eigenschaften interpretiert werden? Zumindest ein String-Array müsste exportiert werden, um solche Szenarien zu adressieren ...

Pro Typ Abhilfe. Nachdem Sie jedoch gesagt haben, dass KeyPath dem Protokoll Equatable entspricht, können Sie eine benutzerdefinierte pro Typ Lösung selbst bereitstellen. Zum Beispiel:

struct Auth { 
    var email: String 
    var password: String 
} 
struct User { 
    var name: String 
    var auth: Auth 
} 

bieten eine Erweiterung für User -basierte Schlüsselpfade:

extension PartialKeyPath where Root == User { 
    var stringValue: String { 
     switch self { 
     case \User.name: return "name" 
     case \User.auth: return "auth" 
     case \User.auth.email: return "auth.email" 
     case \User.auth.password: return "auth.password" 
     default: fatalError("Unexpected key path") 
    } 
} 

Nutzung:

let name: KeyPath<User, String> = \User.name 
let email: KeyPath<User, String> = \User.auth.email 
print(name.stringValue) /* name */ 
print(email.stringValue) /* auth.email */ 

Ich würde diese Lösung für Produktionscode nicht wirklich empfehlen, angesichts der etwas hohen Wartung, etc. Aber da Sie neugierig waren, gibt Ihnen das zumindest einen Weg nach vorne;)

Verwandte Themen