这里是上面的toDictionary的完整版本。
它使用toDictionary()方法作为Mirror的扩展。
我添加了递归,使其可以处理任何深度的类层次结构。
它在self >> self.super >> self.super.super ..等上获取mirror.children
您还可以告诉它停止/不包括某个类,例如 "NSObject" "UIViewController"。
我计划将其用于将我的Model对象转换为CKRecord。
优点:模型对象本身不需要知道CKRecord。
“辅助方法”如上所述也可以工作,但是由于那只使用Mirror中的方法,因此将所有代码添加为Mirror的扩展也是有道理的。
只需将下面的所有代码粘贴到Playground中即可运行。
在代码的底部块处开始执行,请参见:
// EXECUTION STARTS HERE
import UIKit
class ClassNSObjectA : NSObject{
var textA = "Some textA"
var numA = 1111
var dateA = NSDate()
var arrayA = ["A1", "A2"]
}
class ClassNSObjectB : ClassNSObjectA{
var textB = "Some textB"
var numB = 1111
var dateB = NSDate()
var arrayB = ["B1", "B2"]
}
class ClassNSObjectC : ClassNSObjectB{
var textC = "Some textC"
var numC = 1111
var dateC = NSDate()
var arrayC = ["C1", "C2"]
}
class ClassASwift {
var textA = "A Swift"
var numA = 1111
var dateA = NSDate()
var arrayA = ["A1Swift", "A2Swift"]
}
class ClassBSwift : ClassASwift{
var textB = "B Swift"
var numB = 1111
var dateB = NSDate()
var arrayB = ["B1Swift", "B2Swift"]
}
class ClassCSwift : ClassBSwift{
var textC = "C Swift"
var numC = 1111
var dateC = NSDate()
var arrayC = ["C1Swift", "C2Swift"]
}
extension Mirror {
func objectToDictionary(stopAtParentClassName : String?) -> [String: AnyObject]{
let dict: [String: AnyObject] = objectToDictionaryForMirror(self, stopAtParentClassName: stopAtParentClassName)
return dict
}
func objectToDictionaryForMirror(mirror: Mirror, stopAtParentClassName : String?) -> [String: AnyObject]{
var dictOfIVars = [String: AnyObject]()
let classname = "\(mirror.subjectType)"
print("classname:\(classname)")
let stopAtParentClassName_ = stopAtParentClassName ?? ""
if (classname == stopAtParentClassName_){
print("NSObject found - skipNSObjectRoot is true - SKIP this class - return empty dictionary")
}else{
for case let (label?, value) in mirror.children {
print("PROP [\(classname)] label:[\(label)] value:[\(value)]")
}
for property in mirror.children {
if let propertyName = property.label {
dictOfIVars[propertyName] = property.value as? AnyObject
}
}
if let superclassMirror = mirror.superclassMirror() {
let dictOfIVarsForSuperClass : [String: AnyObject] = objectToDictionaryForMirror(superclassMirror, stopAtParentClassName: stopAtParentClassName)
dictOfIVars.merge(dictOfIVarsForSuperClass)
}else{
print("class has no superclassMirror")
}
}
return dictOfIVars
}
}
extension Dictionary{
mutating func merge(dictionary: Dictionary<Key, Value>) {
for (key, value) in dictionary {
self[key] = value
}
}
}
func dumpDictionary(anyObject: AnyObject, stopAtParentClassName: String?){
let mirror = Mirror(reflecting: anyObject)
let dictOfIVars = mirror.objectToDictionary(stopAtParentClassName)
print("*****************************************************")
print("*********** SCAN COMPLETE - DUMP DICT INFO***********")
print("*****************************************************")
print("dictOfIVars:\r\(dictOfIVars)")
print("KEYS:")
for key in dictOfIVars.keys.sort(){
print(key)
}
print("dictOfIVars.keys.count:\(dictOfIVars.keys.count)")
}
print("======================================================================")
print("START TESTS - open console below ")
print("======================================================================")
print("")
print("=====================================================================================================================")
print("========== TEST 1: recursively iterate up tree of NSObject subclasses - include root object 'NSObject' in scan")
print("=====================================================================================================================")
let instanceC : ClassNSObjectB = ClassNSObjectC()
dumpDictionary(instanceC, stopAtParentClassName: "NSObject")
print("")
print("=====================================================================================================================")
print("========== TEST 2: recursively iterate up tree of NSObject subclasses - DO NOT include root object 'NSObject' in scan")
print("=====================================================================================================================")
dumpDictionary(instanceC, stopAtParentClassName: nil)
print("")
print("======================================================================================================================")
print("========== TEST 3: recursively iterate up tree of Swift subclasses")
print("======================================================================================================================")
let classBSwift : ClassBSwift = ClassCSwift()
dumpDictionary(classBSwift, stopAtParentClassName: nil)
输出
======================================================================
START TESTS - open console below
======================================================================
=====================================================================================================================
========== TEST 1: recursively iterate up tree of NSObject subclasses - include root object 'NSObject' in scan
=====================================================================================================================
classname:ClassNSObjectC
PROP [ClassNSObjectC] label:[textC] value:[Some textC]
PROP [ClassNSObjectC] label:[numC] value:[1111]
PROP [ClassNSObjectC] label:[dateC] value:[2016-02-17 13:37:35 +0000]
PROP [ClassNSObjectC] label:[arrayC] value:[["C1", "C2"]]
classname:ClassNSObjectB
PROP [ClassNSObjectB] label:[textB] value:[Some textB]
PROP [ClassNSObjectB] label:[numB] value:[1111]
PROP [ClassNSObjectB] label:[dateB] value:[2016-02-17 13:37:35 +0000]
PROP [ClassNSObjectB] label:[arrayB] value:[["B1", "B2"]]
classname:ClassNSObjectA
PROP [ClassNSObjectA] label:[textA] value:[Some textA]
PROP [ClassNSObjectA] label:[numA] value:[1111]
PROP [ClassNSObjectA] label:[dateA] value:[2016-02-17 13:37:35 +0000]
PROP [ClassNSObjectA] label:[arrayA] value:[["A1", "A2"]]
classname:NSObject
NSObject found - skipNSObjectRoot is true - SKIP this class - return empty dictionary
*****************************************************
*********** SCAN COMPLETE - DUMP DICT INFO***********
*****************************************************
dictOfIVars:
["numB": 1111, "numC": 1111, "arrayB": (
B1,
B2
), "dateA": 2016-02-17 13:37:35 +0000, "dateC": 2016-02-17 13:37:35 +0000, "dateB": 2016-02-17 13:37:35 +0000, "arrayC": (
C1,
C2
), "textC": Some textC, "arrayA": (
A1,
A2
), "textA": Some textA, "numA": 1111, "textB": Some textB]
KEYS:
arrayA
arrayB
arrayC
dateA
dateB
dateC
numA
numB
numC
textA
textB
textC
dictOfIVars.keys.count:12
=====================================================================================================================
========== TEST 2: recursively iterate up tree of NSObject subclasses - DO NOT include root object 'NSObject' in scan
=====================================================================================================================
classname:ClassNSObjectC
PROP [ClassNSObjectC] label:[textC] value:[Some textC]
PROP [ClassNSObjectC] label:[numC] value:[1111]
PROP [ClassNSObjectC] label:[dateC] value:[2016-02-17 13:37:35 +0000]
PROP [ClassNSObjectC] label:[arrayC] value:[["C1", "C2"]]
classname:ClassNSObjectB
PROP [ClassNSObjectB] label:[textB] value:[Some textB]
PROP [ClassNSObjectB] label:[numB] value:[1111]
PROP [ClassNSObjectB] label:[dateB] value:[2016-02-17 13:37:35 +0000]
PROP [ClassNSObjectB] label:[arrayB] value:[["B1", "B2"]]
classname:ClassNSObjectA
PROP [ClassNSObjectA] label:[textA] value:[Some textA]
PROP [ClassNSObjectA] label:[numA] value:[1111]
PROP [ClassNSObjectA] label:[dateA] value:[2016-02-17 13:37:35 +0000]
PROP [ClassNSObjectA] label:[arrayA] value:[["A1", "A2"]]
classname:NSObject
class has no superclassMirror
*****************************************************
*********** SCAN COMPLETE - DUMP DICT INFO***********
*****************************************************
dictOfIVars:
["numB": 1111, "numC": 1111, "arrayB": (
B1,
B2
), "dateA": 2016-02-17 13:37:35 +0000, "dateC": 2016-02-17 13:37:35 +0000, "dateB": 2016-02-17 13:37:35 +0000, "arrayC": (
C1,
C2
), "textC": Some textC, "arrayA": (
A1,
A2
), "textA": Some textA, "numA": 1111, "textB": Some textB]
KEYS:
arrayA
arrayB
arrayC
dateA
dateB
dateC
numA
numB
numC
textA
textB
textC
dictOfIVars.keys.count:12
======================================================================================================================
========== TEST 3: recursively iterate up tree of Swift subclasses
======================================================================================================================
classname:ClassCSwift
PROP [ClassCSwift] label:[textC] value:[C Swift]
PROP [ClassCSwift] label:[numC] value:[1111]
PROP [ClassCSwift] label:[dateC] value:[2016-02-17 13:37:35 +0000]
PROP [ClassCSwift] label:[arrayC] value:[["C1Swift", "C2Swift"]]
classname:ClassBSwift
PROP [ClassBSwift] label:[textB] value:[B Swift]
PROP [ClassBSwift] label:[numB] value:[1111]
PROP [ClassBSwift] label:[dateB] value:[2016-02-17 13:37:35 +0000]
PROP [ClassBSwift] label:[arrayB] value:[["B1Swift", "B2Swift"]]
classname:ClassASwift
PROP [ClassASwift] label:[textA] value:[A Swift]
PROP [ClassASwift] label:[numA] value:[1111]
PROP [ClassASwift] label:[dateA] value:[2016-02-17 13:37:35 +0000]
PROP [ClassASwift] label:[arrayA] value:[["A1Swift", "A2Swift"]]
class has no superclassMirror
*****************************************************
*********** SCAN COMPLETE - DUMP DICT INFO***********
*****************************************************
dictOfIVars:
["numB": 1111, "numC": 1111, "arrayB": (
B1Swift,
B2Swift
), "dateA": 2016-02-17 13:37:35 +0000, "dateC": 2016-02-17 13:37:35 +0000, "dateB": 2016-02-17 13:37:35 +0000, "arrayC": (
C1Swift,
C2Swift
), "textC": C Swift, "arrayA": (
A1Swift,
A2Swift
), "textA": A Swift, "numA": 1111, "textB": B Swift]
KEYS:
arrayA
arrayB
arrayC
dateA
dateB
dateC
numA
numB
numC
textA
textB
textC
dictOfIVars.keys.count:12