Mirror
反射:是指可以动态获取属性、成员信息,在运行时可以调用方法、属性等行为的特性
Swift并不像OC那样,Swift是静态语言(OC支持runtime动态操作),在使用OC时很少强调反射概念,因为OC的Runtime要比其他语言中的反射强大的多。
Swift标准库提供了反射机制(Mirror),用来访问成员信息(对于函数是没法进行访问的,如果需访问,需要将函数定义为属性信息)
enum LTSeasonEnum {
case FIRST,SECOND,THIRD,FORTH
}
class LTMirror: NSObject{
var age:Int=18
var season: LTSeasonEnum = .FIRST
func printSeason(){
print("************")
}
}
let mirror =Mirror(reflecting:LTMirror.self)
for c in mirror.children{
print("\(c.label ??"0"):\(c.value)")
}
运行上面代码,没有任何打印。因为Mirror中传入的参数不对,应该是传入实例对象
let mir = LTMirror()
let mirror2 =Mirror(reflecting:mir.self)
for c in mirror2.children{
//通过label输出当前的名称,value输出当前反射的值
print("\(c.label ??"0"):\(c.value)")
}
运行上述代码输出:
age:18
season:FIRST
标准库提供了反射机制来访问成员信息;Swift基于Mirror的结构体来实现,可以通过为具体的实例创建一个Mirror对象,然后就可以通过它查询这个实例
进入到源码(Mirror.swift),看Mirror的定义
Mirror initMirror的init方法,传入的是一个Any类型
childrenchildren其实是一个AnyCollection,接收一个泛型
Child,是一个元祖类型,由可选标签和值构成
通过源码可知通过label、value能打印出名称和value的原因。
即可以在编译时期且不用知道任何类型信息情况下,在Child的值上用Mirror去遍历整个对象的层级视图
根据Mirror的特性,可以通过Mirror做JSON解析
class LTMirrorJson{
var age: Int = 18
var name: String = "TOTTI"
}
func formatJson(_ object: Any) -> Any{
let mirror =Mirror(reflecting: object)
guard !mirror.children.isEmpty else{
return object
}
var keyValue: [String:Any] = [:]
for child in mirror.children{
if let keyName = child.label{
keyValue[keyName] =formatJson(child.value)
}else{
print("child")
}
}
return keyValue
}
let mj = LTMirrorJson()
print(formatJson(mj))
上述代码,运行结果为:["age": 18, "name": "TOTTI"]
上面代码只是针对LTMirrorJson的JSON解析,为了方便其他类使用,可以将Json解析抽取称一个协议,然后提供一个默认实现,让类遵守协议
//定义一个JSON解析协议
protocol LTGeneralJSONMap{
func formatJson() ->Any
}
//提供一个默认实现
extension LTGeneralJSONMap{
func formatJson() ->Any{
let mirror =Mirror(reflecting:self)
guard !mirror.children.isEmpty else{
return self
}
//定义用于存储json数据的字典
var jsonMap: [String:Any] = [:]
for child in mirror.children{
if let value = child.value as? LTGeneralJSONMap{
if let key = child.label {
jsonMap[key] = value.formatJson()
}else{
print("error key is nil")
}
}else{
print("the json protocol is not implement")
}
}
return jsonMap
}
}
上述代码实现了通用的json解析,如果使用的话,只需实现LTGeneralJSONMap协议即可
class LTJsonClass: LTGeneralJSONMap{
var age:Int=18
var name: String = "TOTTI"
}
var jc = LTJsonClass()
print(jc.formatJson())
运行输出:
the json protocol is not implement
the json protocol is not implement
[:]
并不是我们想象中的结果,原因是类中属性的类型也需要遵守LTGeneralJSONMap协议
增加如下代码
extension Int: LTGeneralJSONMap{}
extension String: LTGeneralJSONMap{}
输出结果如下:
["age": 18, "name": "TOTTI"]
网友评论