iOS 之Mirror的使用
使用Mirror可以在不获取对象文件的情况下,知悉该对象所有的属性,不管是私有还是公开的。

class Animal: NSObject {
    private var food = ""
    override init() {
        super.init()
        self.food = "meat"
    }
}

class Human: Animal {
    private var height: Float = 0.0
    private var weight: Float = 0.0
    override init() {
        super.init()
        self.height = 170
        self.weight = 120
    }
}

class Person: Human {
    private var name: String = ""               //String
    private var gender: String = ""             //String
    private var family: [Person] = []           //Array<Person>
    private var pDic: [String: String] = [:]    //Dictionary<String, String>

    override init() {
        super.init()
        self.name = "zhou"
        self.gender = "men"
        self.family = []
        self.pDic = ["hair": "black", "eyes": "black"]
    }
}

随便定义三个类,Person -> Human -> Animal 这是他们的继承关系。

let p = Person()
var mir: Mirror = Mirror(reflecting: p)
for item in mir.children {
    let value = item.value
    let valueType = "\(Mirror(reflecting: value).subjectType)"
    debugPrint(item.label!, item.value, valueType)
//    p.setValue(<#T##value: Any?##Any?#>, forKey: <#T##String#>)
}
=============debugPrint=================
"name" "zhou" "String"
"gender" "men" "String"
"family" [] "Array<Person>"
"pDic" ["hair": "black", "eyes": "black"] "Dictionary<String, String>"

以上初始化了一个Person类对象p,然后查看其所有的属性并打印字段名、值、值类型。拿到了这些信息,就可以做一些操作了比如setValue:forKey直接修改属性值。而且还可以获取对象所继承的相关信息,看以下例子:

let p = Person()
var mir: Mirror = Mirror(reflecting: p)

let baseType = Animal.self
var selfMirrorType = mir.subjectType

while true {
    for item in mir.children {
        let value = item.value
        let valueType = "\(Mirror(reflecting: value).subjectType)"
        debugPrint(item.label ?? "label", item.value, valueType)
    }
    debugPrint("===========================================")
    if let superclassMirror = mir.superclassMirror {
        mir = superclassMirror
        selfMirrorType = superclassMirror.subjectType
    } else {
        break
    }
}

循环查找对象的superclassMirror直到为空,以下是打印信息:先打印Person类,再是继承的Human类信息,最后是基类Animal信息。

"name" "zhou" "String"
"gender" "men" "String"
"family" [] "Array<Person>"
"pDic" ["hair": "black", "eyes": "black"] "Dictionary<String, String>"
"==========================================="
"height" 170.0 "Float"
"weight" 120.0 "Float"
"==========================================="
"food" "meat" "String"
"==========================================="
"==========================================="

如果你不想Mirror打印一个类所有属性的话,可以给类添加一个扩展遵循协议CustomReflectable:当对Person类使用Mirror时,我们只让查看name和gender属性。

extension Person: CustomReflectable {
    var customMirror: Mirror {
        return Mirror(Person.self, children: ["name": self.name, "gender": self.gender], displayStyle: .class, ancestorRepresentation: .suppressed)
    }
}

let p = Person()
var mir: Mirror = Mirror(reflecting: p)
for item in mir.children {
    let value = item.value
    let valueType = "\(Mirror(reflecting: value).subjectType)"
    debugPrint(item.label!, item.value, valueType)
}
==========================debugPrint=====================================
"name" "zhou" "String"
"gender" "men" "String"

ps;iOS开发交流技术群:欢迎你的加入 ,不管你是大牛还是小白都欢迎入驻 ,分享BAT,阿里面试题、面试经验,讨论技术, 大家一起交流学习成长!