2014-09-23 4 views
30

Итак, я пытаюсь получить фактическое имя переменной как String в Swift, но не нашел способ сделать это ... или, возможно, я рассматриваю эту проблему и решение в плохой угол.Получите фактическое имя Swift Variable как String

Так что это в основном то, что я хочу сделать:

var appId: String? = nil 

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

К сожалению, я не смог найти в яблоневых документы все, что близко к этому, но это:

varobj.self or reflect(var).summary 

однако, это дает информацию о том, что внутри самой переменной или тип переменной в этом случае является String, и я хочу фактическое имя переменной.

+0

Что вы на самом деле пытаетесь получить от имени переменной? Это не JavaScript или Python. Динамические языки, подобные этим, хранят такую ​​информацию во время выполнения. В Swift имена переменных являются просто удобством для программиста (чтобы дать именам людей адресам памяти), и они не существуют в программе во время выполнения. – Alexander

ответ

14

В соответствии с обновленной от this answer, она поддерживается в Swift 3 через #keyPath

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

Я буду плотиной ... спасибо за головы. Я боялся этого из-за того, насколько новый язык.Хм, есть ли способ сделать такое отображение? –

+0

О, спасибо, я набрал это заявление выше, прежде чем вы редактируете. Большое спасибо, посмотрим. –

+0

Если вам нужно свойство или переменные метаданные, вам придется самому справиться с этим. – ColinE

0

Лучшее решение Here

От данной ссылке

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

Это решение не дает имена свойств в родительском классы. правильно? – vivin

0

Я придумал swif t, но, к сожалению, он не работает с Inta Float's и Double's Я верю.

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) 

Он сравнивает адреса памяти для свойств объекта и видит, если они совпадают. Причина, по которой он не работает для Inta Float и Double, потому что они не имеют тип anyobject, хотя вы можете передать их как anyobject, когда вы это сделаете, они преобразуются в NSNumbers. поэтому адрес памяти изменяется. they talk about it here.

Для моего приложения это не мешало мне вообще, потому что мне это было нужно только для пользовательских классов. Так что, может быть, кто-то найдет это полезным. Если кто-то может сделать эту работу с другими типами данных, тогда это будет довольно круто.

+0

Я всегда получаю «пустую строку», когда я выполняю переменные класса домена ... Могу ли я помочь отладке, потому что у меня нет более глубокого понимания зеркал и других вещей? @david rees – vivin

+0

Когда вы говорите переменные класса домена, что вы имеете в виду? Я не могу помочь вам, если вы не представите мне пример. –

+0

По доменному объекту, который я имею в виду, класс java bean/класс объектов переноса. – vivin

42

Это официально поддерживается в Swift 3 с использованием #keyPath()

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

Пример использования будет выглядеть следующим образом:

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

EDIT - В Swift 4 мы имеем что-то еще лучше:

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

// or 

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

Сокращение является долгожданным дополнением, и возможность ссылки на ключевые слова с переменной чрезвычайно велика

+0

Спасибо, мой герой! Я бы просто сказал, что 2 метода 'value (forKeyPath:)' и 'setValue (_, forKeyPath)' позволяют выполнять изменение с помощью этого использования #keyPath(). IMO это должен быть новый принятый ответ для Swift 3. – Tulleb

+0

Что такое имя переменной в этом примере и где оно отправляется/задается как строка? – Confused

+0

«Переменная» не является переменной. Это класс/структура, определенные где-то еще в коде. Что-то вроде 'class Person {let firstName: String}'. Если этот пример выглядит странно, я предлагаю прочитать [NSPredicates] (https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/Predicates/Articles/pSyntax.html), они очень эффективны, когда работа с коллекциями – Andrew

Смежные вопросы