Get a Swift Variable's Actual Name as String

后端 未结 6 2016
借酒劲吻你
借酒劲吻你 2020-11-29 04:40

So I am trying to get the Actual Variable Name as String in Swift, but have not found a way to do so... or maybe I am looking at this problem and solution in a bad angle.

相关标签:
6条回答
  • 2020-11-29 04:59

    This is officially supported in Swift 3 using #keyPath()

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

    Example usage would look like:

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

    In Swift 4 we have something even better: \KeyPath notation

    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")
    

    The shorthand is a welcome addition, and being able to reference keypaths from a variable is extremely powerful

    0 讨论(0)
  • 2020-11-29 05:05

    This works:

    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)
    }
    
    0 讨论(0)
  • 2020-11-29 05:09

    I've come up with a swift solution, however unfortunately it doesn't work with Ints, Floats, and Doubles I believe.

    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)
    

    It compares memory addresses for an object's properties and sees if any match. The reason it doesn't work for Ints, Floats, and Doubles because they're not of type anyobject, although you can pass them as anyobject, when you do so they get converted to NSNumbers. therefore the memory address changes. they talk about it here.

    For my app, it didn't hinder me at all because I only needed it for custom classes. So maybe someone will find this useful. If anyone can make this work with the other datatypes then that would be pretty cool.

    0 讨论(0)
  • 2020-11-29 05:12

    The best solution is Here

    From given link

    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;
    }
    

    }

    0 讨论(0)
  • 2020-11-29 05:13

    As per the updated from this answer, it is supported in Swift 3 via #keyPath

    NSPredicate(format: "%K == %@", #keyPath(Person.firstName), "Andrew")
    
    0 讨论(0)
  • 2020-11-29 05:13

    This is my solution

    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 ?? "")
    }
    

    print will be

    name
    lastName
    
    0 讨论(0)
提交回复
热议问题