简体   繁体   中英

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

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.

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, eg no extensions...):

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

let allTrees = Tree.allCases.map{ $0.rawValue }
print(allTrees) // => ["Bark", "Roots"]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM