Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Iterate over static properties of a struct

Is there a simple way to iterate over all of the properties of a struct? The approach for non-static properties that I am familiar with is using Mirror, but this returns an empty array when the struct contains only static properties. Here's an example of what I am trying to achieve:

struct Tree {
    static let bark = "Bark"
    static let roots = "Roots"
}

let treeParts = [String]()
// insert code here to make treeParts = ["Bark", "Roots"]
like image 489
mattgabor Avatar asked Sep 06 '16 00:09

mattgabor


2 Answers

I was also looking for this and ended up using an enum. It's a good thing if you only have a list of static values (but enums also come with some limitations, e.g. no extensions...):

enum Tree: String, CaseIterable {
    case bark = "Bark"
    case roots = "Roots"
}

let allTrees = Tree.allCases.map{ $0.rawValue }
print(allTrees) // => ["Bark", "Roots"]
like image 189
benjamin.ludwig Avatar answered Nov 14 '22 02:11

benjamin.ludwig


Since I also have an interest of how to do this I made the example below. Why not just create the struct with non static properties plus a static instance variable which makes the struct a singleton. The following code sample details an example use case for mapping values of a Person object to a JSON dictionary using the REST API's naming semantics. The property names of PersonJSONKeys have to match the property names of Person.

The code for the allProperties() function comes from How to loop over struct properties in Swift?. You can modify this function easily to only return the values of a structs properties.

struct PersonJSONKeys: PropertyLoopable {
    static let instance: PersonJSONKeys = PersonJSONKeys()
    private init() {}

    let name = "name"
    let firstName = "first_name"
    let age = "age"
}

struct Person: PropertyLoopable {
    let name = "Doe"
    let firstName = "John"
    let age = "18"
}

let person = Person()
let personProperties = person.allProperties()
var personJSON: [String:Any] = [:]

for jsonProperty in PersonJSONKeys.instance.allProperties() {
    let propertyName = jsonProperty.key
    let jsonKey = jsonProperty.value as! String
    personJSON[jsonKey] = personProperties[propertyName]
}

Since the Struct is now a singleton all of its properties will be initialised only once and the thread safety is given by its static instance variable.

like image 35
blackjacx Avatar answered Nov 14 '22 01:11

blackjacx