Получить фактическое имя переменной Swift в виде строки
Поэтому я пытаюсь получить фактическое имя переменной в виде строки в Swift, но не нашел способа сделать это... или, возможно, я смотрю на эту проблему и ее решение в плохом ракурсе.
Так что это в основном то, что я хочу сделать:
var appId: String? = nil
//This is true, since appId is actually the name of the var appId
if( appId.getVarName = "appId"){
appId = "CommandoFurball"
}
К сожалению, я не смог найти в документах Apple ничего похожего на это, но это:
varobj.self or reflect(var).summary
однако, это дает информацию о том, что находится внутри самой переменной, или о типе переменной в данном случае, являющейся String, и я хочу фактическое имя переменной.
7 ответов
Согласно обновленному ответу, он поддерживается в Swift 3 через #keyPath
NSPredicate(format: "%K == %@", #keyPath(Person.firstName), "Andrew")
Это официально поддерживается в Swift 3 с помощью #keyPath()
https://github.com/apple/swift-evolution/blob/master/proposals/0062-objc-keypaths.md
Пример использования будет выглядеть так:
NSPredicate(format: "%K == %@", #keyPath(Person.firstName), "Wendy")
РЕДАКТИРОВАТЬ - В Swift 4 у нас есть что-то еще лучше:
NSPredicate(format: "%K == %@", \Person.mother.firstName, "Wendy")
// or
let keyPath = \Person.mother.firstName
NSPredicate(format: "%K == %@", keyPath, "Andrew")
Сокращение является долгожданным дополнением, и возможность ссылаться на ключевые пути из переменной является чрезвычайно мощным
Это мое решение
class Test {
var name: String = "Ido"
var lastName: String = "Cohen"
}
let t = Test()
let mirror = Mirror(reflecting: t)
for child in mirror.children {
print(child.label ?? "")
}
печать будет
name
lastName
Это работает:
struct s {
var x:Int = 1
var y:Int = 2
var z:Int = 3
}
var xyz = s()
let m = Mirror(reflecting: xyz)
print(m.description)
print(m.children.count)
for p in m.children {
print(p.label as Any)
}
Завершение принятого ответа для расширений:
- Имущество должно быть
@objc
.
var appId: строка? { .... }
- Вам нужно использовать
#keyPath
синтаксис,\
нотация пока не поддерживается для расширений.
#keyPath(ВашКласс.appId)
Я придумал быстрое решение, однако, к сожалению, оно не работает с Flo's от Int и Double, я полагаю.
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)
Он сравнивает адреса памяти для свойств объекта и определяет, совпадают ли они. Причина, по которой он не работает для типов Float и Double в Int, потому что они не относятся к типу anyobject, хотя вы можете передать их как anyobject, когда вы это сделаете, они преобразуются в номера NSN. поэтому адрес памяти меняется. они говорят об этом здесь.
Для моего приложения это совсем не мешало мне, потому что оно мне было нужно только для пользовательских классов. Так что, возможно, кто-то найдет это полезным. Если кто-то может сделать эту работу с другими типами данных, это было бы довольно круто.
Лучшее решение здесь
По данной ссылке
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;
}
}