一、Swift反射
所谓反射就是可以动态获取类型、成员信息,在运行时可以调用方法、属性等行为的特性。 在使用OC
开发时很少强调其反射概念,因为OC的Runtime
要比其他语言中的反射强大的多。不过在Swift
中并不提倡使用Runtime
,而是像其他语言一样使用反射(Reflect
),即使目前Swift
中的反射功能还比较弱,只能访问获取类型、成员信息。
Swift
的反射机制是基于一个叫Mirror
的结构体来实现的。你为具体的实例创建一个Mirror
对象,然后就可以通过它查询这个实例
Mirror结构体常用属性:
subjectType
:对象类型children
:反射对象的属性集合displayStyle
:反射对象展示类型
下面来简单介绍下Mirror的使用:
//定义一个类来进行测试 class Person { var name: String? var age: Int = 0 } //创建一个对象并初始化 let p = Person() p.name = "小强" p.age = 13 //1. 创建对象的反射,获取对象类型 let mirror: Mirror = Mirror(reflecting:p) print("获取对象类型\(mirror.subjectType)") // 打印出:获取对象类型Person //2. 获取对象属性名以及对应的值 for p in mirror.children { let propertyNameString = p.label! //属性名使用!,因为label是optional类型 let value = p.value //属性的值 print("\(propertyNameString)的值为\(value)") } /* 打印: name的值为Optional("小强") age的值为13 */ //3. 获取指定索引下的属性类型 let children = mirror.children let p0 = children.startIndex.advancedBy(0) //获取name属性的位置索引 let p0Mirror = Mirror(reflecting: children[p0].value) //name的反射 print("获取属性name的类型为\(p0Mirror.subjectType)") //打印:获取属性name的类型为Optional //4. 遍历获取对象所有动态的属性类型 for p in mirror.children { let propertyNameString = p.label! let value = p.value let vMirror = Mirror(reflecting: value) //通过值来创建属性的反射 print("属性\(propertyNameString)类型为\(vMirror.subjectType)") } /* 打印: 属性name类型为Optional 属性age类型为Int */
反射的应用场景现在还比较狭窄,因为功能还不够完善,我提供一个比较常见的反射应用场景,那就是自定义类模型转字典
以下就是自定义类模型转字典实例
//自定义用户类 class User { var name:String = "" //姓名 var nickname:String? //昵称 var age:Int? //年龄 var emails:[String]? //邮件地址 var tels:[Telephone]? //电话 } //电话结构体 struct Telephone { var title:String //电话标题 var number:String //电话号码 } //自定义一个JSON协议 protocol JSON { func toJSONModel() -> Any? } //扩展协议方法,实现一个通用的toJSONModel方法(反射实现) extension JSON { //将模型数据转成可用的字典数据,Any表示任何类型,除了方法类型 func toJSONModel() -> Any? { //根据实例创建反射结构体Mirror let mirror = Mirror(reflecting: self) if mirror.children.count > 0 { //创建一个空字典,用于后面添加键值对 var result: [String:Any] = [:] //遍历实例的所有属性集合 for children in mirror.children { let propertyNameString = children.label! let value = children.value //判断value的类型是否遵循JSON协议,进行深度递归调用 if let jsonValue = value as? JSON { result[propertyNameString] = jsonValue.toJSONModel() } } return result } return self } } //扩展可选类型,使其遵循JSON协议,可选类型值为nil时,不转化进字典中 extension Optional: JSON { //可选类型重写toJSONModel()方法 func toJSONModel() -> Any? { if let x = self { if let value = x as? JSON { return value.toJSONModel() } } return nil } } //扩展两个自定义类型,使其遵循JSON协议 extension User: JSON { } extension Telephone: JSON { } //扩展Swift的基本数据类型,使其遵循JSON协议 extension String: JSON { } extension Int: JSON { } extension Bool: JSON { } extension Dictionary: JSON { } extension Array: JSON { } //创建一个User实例对象模型 let user1 = User() user1.name = "hangge" user1.age = 100 user1.emails = ["hangge@hangge.com","system@hangge.com"] //添加电话 let tel1 = Telephone(title: "手机", number: "123456") let tel2 = Telephone(title: "公司座机", number: "001-0358") user1.tels = [tel1, tel2] //模型转字典 if let model = user1.toJSONModel() { print(model) } /* 打印:【以下打印经过排版,正式的打印是紧凑的】 [ "tels": [ "[1]": [ "title": "公司座机", "number": "001-0358" ], "[0]": [ "title": "手机", "number": "123456" ] ], "name": "hangge", "emails": [ "[1]": "system@hangge.com", "[0]": "hangge@hangge.com" ], "age": 100 ] */