我想循环使用Register or Login
的每个键,并为每个属性打印键及其值。
mystruct
但是使用上面的几行我总是得到这个错误信息:
类型mystruct.Type不符合协议'Sequence'
如何避免收到此消息?
答案 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
}
}