iOS學習筆記48-Swift(八)反射


一、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 ] */


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM