Access properties via subscripting in Swift

笑着哭i 提交于 2019-11-28 11:57:13

(GRMustache author here)

Until a swift-oriented Mustache library is out, I suggest having your classes inherit from NSObject (so that they have the valueForKey: method). GRMustache will then fetch values with this method.

In case this would still not work (blank values in the rendering), you may try to disable GRMustache security features (see https://github.com/groue/GRMustache/blob/master/Guides/security.md#disabling-safe-key-access)

Should you experience any other trouble, please open an issue right into the repository: https://github.com/groue/GRMustache/issues

EDIT February 2, 2015: GRMustache.swift is out: http://github.com/groue/GRMustache.swift

This is a bit of a hack using reflection. Something along the lines of the following could be used.

protocol PropertyReflectable { }

extension PropertyReflectable {
    subscript(key: String) -> Any? {
        let m = Mirror(reflecting: self)
        for child in m.children {
            if child.label == key { return child.value }
        }
        return nil
    }
}

struct Person {
    let name: String
    let age: Int
}

extension Person : PropertyReflectable {}

Then create a Person and access it's keyed properties.

let p = Person(name: "John Doe", age: 18)

p["name"] // gives "John Doe"
p["age"] // gives 18

You could modify the subscript to always return an interpolated string of the property value.

mizerablebr

Using valueForKey should enable you to access properties using their names. Be sure that you're working with a object that inherit NSObject

class people: NSObject {
    var age: NSString = "44"
    var height: NSString = "153"
}

let person:people = people()

let stringVariable = "age"

person.valueForKey("age")
// Print "44"

person.valueForKey("\(stringVariable)")
// Print "44"

Adding some syntax sugar to Benzi's answer:

protocol PropertyReflectable { }

extension PropertyReflectable {
    subscript(key: String) -> Any? {
        let m = Mirror(reflecting: self)
        return m.children.first { $0.label == key }?.value
    }
}

struct Person {
    let name: String
    let age: Int
}

extension Person : PropertyReflectable {}

Then create a Person and access it's keyed properties.

let p = Person(name: "John Doe", age: 18)

p["name"] // gives "John Doe"
p["age"] // gives 18

Shim's answer above doesn't work anymore in Swift 4. There are two things you should be aware of.

First of all, if you want to use value(forKey:) function, your class must inherit NSObject.

Secondly, since Objective-C doesn't know anything about value type, you have to put the @objc keyword in front of your value type properties and Swift will do the heavy-lifting for you.

Here is the example:

import Foundation

class Person: NSObject {
    @objc var name: String = "John Dow"
    @objc var age: Int = 25
    @objc var height: Int = 180

    subscript(key: String) -> Any? {
        return self.value(forKey: key)
    }
}

let person: Person = Person()

person["name"] // "John Dow"
person["age"] // 25
person["height"] // 180

I suppose you could do:

class User {
    let properties = Dictionary<String,String>()

    subscript(key: String) -> String? {
        return properties[key]
    }

    init(name: String, title: String) {
        properties["name"] = name
        properties["title"] = title
    }
}

Without knowing your use case I would strongly advise against doing this.

Another approach:

class User {
    var name : String
    var title : String

    subscript(key: String) -> String? {
        switch key {
            case "name" : return name
            case "title" : return title
            default : return nil
        }
    }

    init(name: String, title: String) {
        self.name = name
        self.title = title
    }
}

It might be worth noting that Swift doesn't appear to currently support reflection by names. The reflect function returns a Mirror whose subscript is Int based, not String based.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!