首页 > 解决方案 > 如何获取嵌套结构中的所有属性名称

问题描述

假设我有以下结构:

struct Location: Codable, Loopable {
    var altitude: Double?
    var coordinate: Coordinate?
    struct Coordinate: Codable, Loopable {
        var latitude: Double?
        var longitude: Double?
    }
    var course: Double?
    var courseAccuracy: Double?
    var floor: Floor?
    struct Floor: Codable, Loopable {
        var level: Int?
    }
    var horizontalAccuracy: Double?
    var speed: Double?
    var speedAccuracy: Double?
    var timestamp: Timestamp?
    struct Timestamp: Codable, Loopable {
        var year: Int?
        var month: Int?
        var day: Int?
        var hour: Int?
        var minute: Int?
        var second: Int?
    }
    var verticalAccuracy: Double?
    var deviceName: String?
    var validPosition: Bool?
}

现在我想为结构实现两种方法。一个应该返回名称中包含所有父级的所有属性名称,另一个应该返回这些属性的所有值。

第一种方法的结果应该如下所示(我们将其命名为 allProperties()):

["altitude", "coordinate.latitude", "coordinate.longitude", "course", "courseAccuracy", "floor.level", "horzontalAccuracy", "speed", "speedAccuracy", "timeststamp.year", "timestamp.month", "timestamp.day", "timeststamp.hour", "timestamp.minute", "timestamp.second", "verticalAccuracy", "deviceName", "validPosition"]

第二种方法的结果(我们将其命名为 allValues())应该如下所示:

[500.0, 48.000000, 10.00000, 120.0, 5.0, 4, 5.0, 3.0, 1.0, 2021, 07, 25, 22, 43, 50, 10.0, "iPhone", true]

如您所见,我的示例结构与其他结构嵌套。在我的真实项目中,结构有两个以上的嵌套“级别”。属性类型也不是唯一的。在最底层,它们都是基本数据类型(Double、Bool、String、Int)。

我试图从这个线程修改解析嵌套结构的解决方案,这似乎是一个优雅的解决方案:How to loop over struct properties in Swift?

现在我的问题:

["some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some"]

到目前为止,这是我的协议代码:

protocol Loopable {
    func allProperties(limit: Int) -> [String]
    func allValues(limit: Int) -> [Any]
}

extension Loopable {
    func allProperties(limit: Int = Int.max) -> [String] {
        return props(obj: self, count: 0, limit: limit)
    }
    
    func allValues(limit: Int = Int.max) -> [Any] {
        return values(obj: self, count: 0, limit: limit)
    }

    private func props(obj: Any, count: Int, limit: Int) -> [String] {
        let mirror = Mirror(reflecting: obj)
        var result: [String] = []
        for (prop, val) in mirror.children {
            guard let prop = prop else { continue }
            if limit == count {
                result.append(prop)
            } else {
                let subResult = props(obj: val, count: count + 1, limit: limit)
                subResult.count == 0 ? result.append(prop) : result.append(contentsOf: subResult)
            }
        }
        return result
    }
    
    private func values(obj: Any, count: Int, limit: Int) -> [Any] {
        let mirror = Mirror(reflecting: obj)
        var result: [Any] = []
        for (_, val) in mirror.children {
            //guard let val = val else { continue }   // This line does not compile
            if limit == count {
                result.append(val)
            } else {
                let subResult = values(obj: val, count: count + 1, limit: limit)
                subResult.count == 0 ? result.append(val) : result.append(contentsOf: subResult)
            }
        }
        return result
    }
}

我在这里做错了什么?为什么属性标签总是“一些”?

标签: swiftstructproperties

解决方案



推荐阅读