mystruct
のすべてのキーをループして、すべてのプロパティについてそのkeyとそのvalueを出力します。
struct mystruct {
var a = "11215"
var b = "21212"
var c = "39932"
}
func loopthrough {
for (key, value) in mystruct {
print("key: \(key), value: \(value)") // Type mystruct.Type does not conform to protocol 'Sequence'
}
}
しかし、上記の数行を使用すると、常に次のエラーメッセージが表示されます。
タイプmystruct.Typeがプロトコル「シーケンス」に準拠していません
このメッセージが表示されないようにするにはどうすればよいですか?
まず、構造体名に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
(型のインスタンスで)ランタイムイントロスペクションを値バインディングパターンマッチングと組み合わせて使用して、プロパティ名と値を抽出できます。後者は、特定のインスタンスのサブ構造を表すために使用されるlabel
インスタンスのオプションのMirror
プロパティをアンラップするために使用されました。
例えば。:
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 */
次のコードを使用して、すべてのプロパティの配列を取得します
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()
プロトコルを実装することを忘れないでください
お役に立てば幸い
私はそれが誰かを助けることを願っています:これは、より複雑なクラス/構造体のための私のバージョンのプロトコルです(オブジェクト内のオブジェクト内のオブジェクト;-))よりエレガントな機能ソリューションがあると確信していますが、これは迅速で汚いソリューションでした。ロギングに一時的に必要なだけでした。
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
}
}