2014-09-23 22 views
30

Quindi sto cercando di ottenere il nome della variabile effettiva come stringa in Swift, ma non ho trovato un modo per farlo ... o forse sto guardando questo problema e la soluzione in un angolo negativo.Ottieni il nome effettivo di una variabile Swift come stringa

Quindi questo è fondamentalmente ciò che voglio fare:

var appId: String? = nil 

//This is true, since appId is actually the name of the var appId 
if(appId.getVarName = "appId"){ 
    appId = "CommandoFurball" 
} 

Purtroppo non sono stati in grado di trovare in documenti di mele tutto ciò che è vicino a questo, ma questo:

varobj.self or reflect(var).summary 

tuttavia, questo fornisce informazioni su cosa c'è dentro la variabile stessa o sul tipo della variabile in questo caso essendo String e voglio il nome effettivo della variabile.

+0

Cosa stai cercando di ottenere dal nome di una variabile? Questo non è JavaScript o Python. I linguaggi dinamici come quelli mantengono quel tipo di informazioni in giro al runtime. In Swift, i nomi delle variabili sono puramente una comodità per il programmatore (in modo da dare nomi umani agli indirizzi di memoria), e non esistono nel programma in fase di runtime. – Alexander

risposta

14

Come da aggiornato da this answer, esso è supportato in Swift 3 tramite #keyPath

NSPredicate(format: "%K == %@", #keyPath(Person.firstName), "Andrew") 
+0

sarei dannato ... grazie per il testa a testa. Avevo paura di questo a causa di quanto sia nuovo il linguaggio.Hmm c'è un modo per essere in grado di fare questo tipo di mappatura? –

+0

Oh, grazie ho digitato questa frase sopra prima della modifica. Grazie mille ci penseremo. –

+0

Se hai bisogno di metadati di proprietà o variabili, dovrai gestirli tu stesso. – ColinE

0

La soluzione migliore è Here

Da dato collegamento

import Foundation 

extension NSObject { 
// 
// Retrieves an array of property names found on the current object 
// using Objective-C runtime functions for introspection: 
// https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtPropertyIntrospection.html 
// 
func propertyNames() -> Array<String> { 
    var results: Array<String> = []; 

    // retrieve the properties via the class_copyPropertyList function 
    var count: UInt32 = 0; 
    var myClass: AnyClass = self.classForCoder; 
    var properties = class_copyPropertyList(myClass, &count); 

    // iterate each objc_property_t struct 
    for var i: UInt32 = 0; i < count; i++ { 
     var property = properties[Int(i)]; 

     // retrieve the property name by calling property_getName function 
     var cname = property_getName(property); 

     // covert the c string into a Swift string 
     var name = String.fromCString(cname); 
     results.append(name!); 
    } 

    // release objc_property_t structs 
    free(properties); 

    return results; 
} 

}

+1

Questa soluzione non fornisce i nomi di proprietà in parent classi. destra? – vivin

0

Sono arrivato con una swif t soluzione, per quanto sfortunatamente non funziona con Int's Float's e Double's credo.

func propertyNameFor(inout item : AnyObject) -> String{ 
    let listMemAdd = unsafeAddressOf(item) 
    let propertyName = Mirror(reflecting: self).children.filter { (child: (label: String?, value: Any)) -> Bool in 
     if let value = child.value as? AnyObject { 
      return listMemAdd == unsafeAddressOf(value) 
     } 
     return false 
     }.flatMap { 
      return $0.label! 
    }.first ?? "" 

    return propertyName 
} 

var mutableObject : AnyObject = object 
let propertyName = MyClass().propertyNameFor(&mutableObject) 

Confronta gli indirizzi di memoria per le proprietà di un oggetto e vede se c'è una corrispondenza. La ragione per cui non funziona con Flo's e Double di Int perché non sono di tipo anyobject, anche se puoi passarli come anyobject, quando lo fai vengono convertiti in NSNumbers. quindi l'indirizzo di memoria cambia. they talk about it here.

Per la mia app, non mi ha affatto ostacolato perché ne avevo solo bisogno per le classi personalizzate. Quindi forse qualcuno lo troverà utile. Se qualcuno può far funzionare questo lavoro con gli altri tipi di dati, sarebbe molto interessante.

+0

Ho sempre "" una stringa vuota, quando eseguo le variabili della mia classe dominio ... Puoi aiutarmi a eseguire il debug cos non ho una comprensione più profonda su mirror e altre cose? @david rees – vivin

+0

Quando dici variabili di classe dominio cosa intendi? Non posso aiutarti se non mi fornisci un esempio. –

+0

Per oggetto dominio, classe classe java/classe oggetto trasferimento .. – vivin

42

Questo è ufficialmente supportato a Swift 3 utilizzando #keyPath()

https://github.com/apple/swift-evolution/blob/master/proposals/0062-objc-keypaths.md

esempio d'uso potrebbe essere simile:

NSPredicate(format: "%K == %@", #keyPath(Person.firstName), "Wendy") 

EDIT - In Swift 4 abbiamo qualcosa di ancora migliore:

NSPredicate(format: "%K == %@", \Person.mother.firstName, "Wendy") 

// or 

let keyPath = \Person.mother.firstName 
NSPredicate(format: "%K == %@", keyPath, "Andrew") 

La stenografia è un'aggiunta benvenuta e la possibilità di fare riferimento a keypath da una variabile è estremamente efficace.

+0

Grazie mio eroe! Vorrei solo dire che i due metodi 'value (forKeyPath:)' e 'setValue (_, forKeyPath)' consentono di effettuare cambiamenti attraverso questo #keyPath() uso. IMO questa dovrebbe essere la nuova risposta accettata per Swift 3. – Tulleb

+0

Qual è il nome della variabile in questo esempio e dove viene inviato/dato come stringa? – Confused

+0

La "variabile" non è affatto una variabile. Questa è una classe/struct definita da qualche altra parte nel codice. Qualcosa come 'class Person {let firstName: String}'. Se l'esempio ti sembra strano ti suggerisco di leggere su [NSPredicates] (https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/Predicates/Articles/pSyntax.html), sono molto potenti quando lavorare con le raccolte – Andrew

Problemi correlati