所謂反射就是能夠動態獲取類型、成員信息,在運行時能夠調用方法、屬性等行爲的特性。 在使用OC
開發時不多強調其反射概念,由於OC的Runtime
要比其餘語言中的反射強大的多。不過在Swift
中並不提倡使用Runtime
,而是像其餘語言同樣使用反射(Reflect
),即便目前Swift
中的反射功能還比較弱,只能訪問獲取類型、成員信息。json
Swift
的反射機制是基於一個叫Mirror
的結構體來實現的。你爲具體的實例建立一個Mirror
對象,而後就能夠經過它查詢這個實例swift
subjectType
:對象類型children
:反射對象的屬性集合displayStyle
:反射對象展現類型//定義一個類來進行測試 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 ] */