/* Reflection反射 和 Mirror镜像 Java 中的Reflection反射 是一种在运行时检测、访问或者修改类型的行为的特性。 一般的静态语言类型的结构和方法的调用等都是在编译时决定,开发者能做的很多时候只是使用控制流(if, switch)来决定做出怎样的设置或者调用哪个方法。 而反射特性可以让我们有机会再运行的时候通过某些条件实时地调用的方法,或者甚至向某个类型动态的设置甚至加入属性及方法,是只用非常灵活和强大的语言特性。 Object-C 中不经常提及 ‘反射’这样的词语,因为 Object-C的运行时比一般的反射还要灵活和强大。 比如 NSClassFromString, @selector("methodName") Swift 中抛开了 Object-C 的运行时部分,功能要弱很多,但是也有反射相关的内容 现在的隐式转换必须使用 ‘字面量转换’的方式进行 Mirror 镜像 */struct Persion { let name: String let age: Int}let xiaoMing = Persion(name: "XiaoMing", age: 16)// r 是 MirrorType, Mirror for Persionlet r = Mirror(reflecting: xiaoMing)print("xiaoMing 是\(r.displayStyle)") // "xiaoMing 是Optional(struct)"print("属性个数:\(r.children.count)")for child in r.children { print("属性名:\(child.label),值:\(child.value)")}/* 属性个数:2 属性名:Optional("name"),值:XiaoMing 属性名:Optional("age"),值:16 *//* 通过 Mirror 初始化得到的结果中包含的元素的描述都被集合在 Children 属性下,是 Child 的集合,Child 是一对键值的多元组 public typealias Child = (label: String?, value: Any) public typealias Children = AnyCollection需要注意的是
这个值可能是多个元素组成的嵌套的行驶,例如属性值是数组或者字典的话,就是嵌套形式
对于一个从对象反射出来的 Mirror,它所包含的信息是完备的。也就是说我们可以在运行时通过 Mirror 的手段了解一个 Swift 类型(NSObject类也可以)的实例的属性信息。
应用1:
任意 model 对象生成对应的 json 描述。可以对等待处理的 Mirror 值进行深度优先的访问,并按照属性的 valueType 将他们归类对应到不同的格式化中。
应用2:
对swift对象做 Object-C 中那样的 valueForKey:的取值。通过比较取到的属性的名字和我们先要取得的key值就行了。
*/
func valueFromA(_ object: Any, key: String) -> Any? {
let mirror = Mirror(reflecting: object)
for child in mirror.children {
let (targetKey, targetMirror) = (child.label, child.value)
if key == targetKey {
return targetMirror
}
}
return nil
}
// 测试
if let name = valueFromA(xiaoMing, key: "name") as? String {
print("通过 key 得到值 :\(name)")
}
/*
需要注意的是,Mirror现在还不稳定,所以避免应用到实际开发中
*/
网友评论