循环通过Swift结构来获取键和值

时间:2018-01-27 12:54:59

标签: swift struct

我想循环使用Register or Login的每个键,并为每个属性打印及其

mystruct

但是使用上面的几行我总是得到这个错误信息:

  

类型mystruct.Type不符合协议'Sequence'

如何避免收到此消息?

4 个答案:

答案 0 :(得分:18)

首先让我们使用 CamelCase 作为结构名称

struct MyStruct {
    var a = "11215"
    var b = "21212"
    var c = "39932"
}

接下来,我们需要创建一个MyStruct类型的值

let elm = MyStruct()

现在,我们可以根据Mirror值构建elm值。

let mirror = Mirror(reflecting: elm)

Mirror值允许我们访问elm的所有属性,在这里

for child in mirror.children  {
    print("key: \(child.label), value: \(child.value)")
}

结果:

  

键:可选(" a"),值:11215

     

键:可选(" b"),值:21212

     

键:可选(" c"),值:39932

答案 1 :(得分:3)

您可以使用运行时内省(在您的类型的实例上)与值绑定模式匹配相结合来提取属性名称和值;后者用于解包用于表示特定实例的子结构的label实例的可选Mirror属性。

E.g:

struct MyStruct {
    let a = "11215"
    let b = "21212"
    let c = "39932"
}

// Runtime introspection on an _instance_ of MyStruct
let m = MyStruct()
for case let (label?, value) in Mirror(reflecting: m)
    .children.map({ ($0.label, $0.value) }) {
    print("label: \(label), value: \(value)")
} /* label: a, value: 11215
     label: b, value: 21212
     label: c, value: 39932 */

答案 2 :(得分:2)

使用以下代码获取所有属性的数组

protocol PropertyLoopable
{
    func allProperties() throws -> [String]
}

extension PropertyLoopable {
    func allProperties() throws -> [String] {

        var result: [String] = []

        let mirror = Mirror(reflecting: self)

        // Optional check to make sure we're iterating over a struct or class
        guard let style = mirror.displayStyle, style == .struct || style == .class else {
            throw NSError()
        }

        for (property,_) in mirror.children {
            guard let property = property else {
                continue
            }
            result.append(property)
         //   result[property] = value
        }

        return result
    }
}

现在只是

let allKeys = try  self.allProperties()

不要忘记实施协议

希望它有用

答案 3 :(得分:0)

我希望它仍然可以帮助某人: 这是我的协议版本,适用于更复杂的类/结构(对象内的对象;对象内的对象;-)) 我确信有一个更优雅的功能解决方案,但这是一个快速而肮脏的解决方案,因为我只需要临时记录即可。

protocol PropertyLoopable {
func allProperties() -> [String: Any]
}


extension PropertyLoopable {
func allProperties() -> [String: Any] {

    var result: [String: Any] = [:]
    let mirror = Mirror(reflecting: self)

    // make sure we're iterating over a struct or class
    guard let style = mirror.displayStyle, style == .struct || style == .class else {
        print("ERROR: NOT A CLASS OR STRUCT")
        return result
    }

    for (property, value) in mirror.children {
        guard let property = property else {
            continue
        }
        // It was a very complicated struct from a JSON with a 4 level deep structure. This is dirty dancing, remove unnecessary "for" loops for simpler structs/classes
        // if value from property is not directly a String, we need to keep iterating one level deeper
        if value is String {
            result.updateValue(value, forKey: property)
        } else {
            let mirror = Mirror(reflecting: value)

            for (property, value) in mirror.children {
                guard let property = property else {
                    continue
                }
                //let's go for a second level
                if value is String {
                    result.updateValue(value, forKey: property)
                } else {
                    let mirror = Mirror(reflecting: value)

                    for (property, value) in mirror.children {
                        guard let property = property else {
                            continue
                        }
                        //3rd level
                        if value is String {
                            result.updateValue(value, forKey: property)
                        } else {
                            let mirror = Mirror(reflecting: value)

                            for (property, value) in mirror.children {
                                guard let property = property else {
                                    continue
                                }
                                result.updateValue(value, forKey: property)
                            }
                        }
                    }
                }
            }
        }
    }
    return result
}

}