Access properties via subscripting in Swift

Matias Korhonen picture Matias Korhonen · Jun 10, 2014 · Viewed 15.6k times · Source

I have a custom class in Swift and I'd like to use subscripting to access its properties, is this possible?

What I want is something like this:

class User {
    var name: String
    var title: String

    subscript(key: String) -> String {
        // Something here
        return // Return the property that matches the key…
    }

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

myUser = User(name: "Bob", title: "Superboss")
myUser["name"] // "Bob"

Update: The reason why I'm looking for this is that I'm using GRMustache to render from HTML templates. I'd like to be able to just pass my model object to the GRMustache renderer…

GRMustache fetches values with the keyed subscripting objectForKeyedSubscript: method and the Key-Value Coding valueForKey: method. Any compliant object can provide values to templates.

https://github.com/groue/GRMustache/blob/master/Guides/view_model.md#viewmodel-objects

Answer

Benzi picture Benzi · Jan 17, 2017

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.