Ответ 1
В соответствии с обновленным с этим ответом он поддерживается в Swift 3 через #keyPath
NSPredicate(format: "%K == %@", #keyPath(Person.firstName), "Andrew")
Поэтому я пытаюсь получить имя фактической переменной как строку в Swift, но не нашел способ сделать это... или, возможно, я рассматриваю эту проблему и решение под плохим углом.
Так что это в основном то, что я хочу сделать:
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, и я хочу фактическое имя переменной.
В соответствии с обновленным с этим ответом он поддерживается в 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 у нас есть кое-что еще лучше: обозначение \KeyPath
https://github.com/apple/swift-evolution/blob/master/proposals/0161-key-paths.md
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
Лучшее решение Здесь
Из данной ссылки
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;
}
}
Я придумал быстрое решение, но, к сожалению, оно не работает с Ints, Floats и Doubles, я считаю.
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)
Он сравнивает адреса памяти для свойств объекта и определяет, совпадают ли они. Причина, по которой он не работает для Ints, Float и Doubles, потому что они не относятся к типу anyobject, хотя вы можете передать их как anyobject, когда вы это сделаете, они конвертируются в NSNumbers. поэтому адрес памяти меняется. они говорят об этом здесь.
Для моего приложения это совсем не мешало мне, потому что оно мне было нужно только для пользовательских классов. Так что, возможно, кто-то найдет это полезным. Если кто-то может сделать эту работу с другими типами данных, это было бы довольно круто.
Это работает:
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)
}