JSON和Model最佳轉(zhuǎn)換的iOS框架: MJExtension-Swift
直接拖拽Reflect文件夾到您的項(xiàng)目中即可,無任何第三方依賴!
文件夾結(jié)構(gòu)說明:
.Coding 歸檔相關(guān)
.Reflect 反射核心包
.Dict2Model 字典轉(zhuǎn)模型
.Model2Dict 模型轉(zhuǎn)字典
注:框架中已為您準(zhǔn)備了大量懶人式示例,并且簡(jiǎn)單到你直接調(diào)用類方法即可查看效果,
1.Parse-Parse8為字典轉(zhuǎn)模型解析系列。
2.Convert1-Convert4為模型轉(zhuǎn)字典系列。
3.Archiver1-Archiver3為歸檔系列。
使用方法如Studetn1.Parse(),Person1.Convert(),Book1.Action()。
我們可以將其理解成是MJExtension的Swift版本,它可以完成類反射、一鍵字典轉(zhuǎn)模型、一鍵模型轉(zhuǎn)字典、一鍵plist轉(zhuǎn)模型以及一鍵歸檔!
MJExtension(OC): https://github.com/CoderMJLee/MJExtension
直接調(diào)用對(duì)象的properties即可枚舉反射您的對(duì)象
p1.properties { (name, type, value) -> Void in println("\(name),\(type),\(value)") }
除了使用對(duì)象調(diào)用之外,你還可以不創(chuàng)建對(duì)象,直接類方法調(diào)用,此時(shí)的value無意義:
Person.properties { (name, type, _) -> Void in println("\(name),\(type)") }
其中name是您的模型的屬性名,type是封裝的ReflectType數(shù)據(jù)類型,value是變量的值, 重度使用者請(qǐng)?jiān)敿?xì)參考ReflectType的封裝,您可以詳細(xì)的知道每個(gè)屬性是什么情況,如:
具體的數(shù)據(jù)類型.是否是基本數(shù)據(jù)類型.是否為數(shù)組.是否為Optional.是否為OC過來的對(duì)象.是否為自定義的Class類
var typeName: String!/** 系統(tǒng)解析出的Type */var typeClass: Any.Type!var disposition: MirrorDisposition!var dispositionDesc: String!/** 是否是可選類型 */var isOptional: Bool = false/** 是否是數(shù)組 */var isArray: Bool = false/** 真實(shí)類型: 可選 + 數(shù)組 */var realType: RealType = .None
,除了上面介紹的功能之外,還加入了仿OC打?。?你可以直接打印您的對(duì)象,比如打印Book1對(duì)象(BOOK1類位于項(xiàng)目中的Archiver1.swift中):
println(book1)
控制臺(tái)會(huì)這樣輸出:
Reflect.Book1 <0x7a09fb10>: {name: tvbprice: 36.6}
附加功能之解析過程的字段映射與字段忽略,子類只需重寫此方法即可:
/** 字段映射 *///使用模型的userModel屬性去解析并接受字典中的user_model鍵值對(duì)func mappingDict() -> [String: String]? { return ["userModel":"user_model"]} /** 字段忽略 *///忽略并且不解析模型的info屬性func ignorePropertiesForParse() -> [String]? { return ["info"]}
您還可以使用以下方法完成字符串向類的轉(zhuǎn)變:
let cls = ClassFromString("Reflect.Person")
不過請(qǐng)注意,這里的字符串是含有命名空間的。
字典轉(zhuǎn)模型非常簡(jiǎn)單,已做各種級(jí)聯(lián),這里不再贅述細(xì)節(jié)了:
let stu1 = Student1.parse(dict: Student1Dict)let stus = Student7.parses(arr: Student7DictArr)
如果你屬性為Bool,你可能會(huì)遇到UndefinedKey,這是因?yàn)閟wift自身的原因,你只需實(shí)現(xiàn)以下方法手動(dòng)解析:
override func setValue(value: AnyObject?, forUndefinedKey key: String) { self.isVip = (value as! Int) != 0}
解析Plist文件,請(qǐng)不要帶后綴:
let author = Author.parsePlist("Author")
模型轉(zhuǎn)字典也非常簡(jiǎn)單,已做各種級(jí)聯(lián),這里不再贅述細(xì)節(jié)了:
let dict = person3.toDict()
歸檔已做了級(jí)聯(lián),使用同樣簡(jiǎn)單,同時(shí)封裝了Caches文件夾的操作,直接保存在Caches文件夾中
歸檔:?jiǎn)蝹€(gè)模型歸檔name可為空,數(shù)組時(shí)name值不可為空,返回歸檔位置
let path1 = Book2.save(obj: book2, name: nil)let path2 = Book3.save(obj: bookArr, name: "book3")
讀?。赫?qǐng)使用同樣的key,如保存沒有使用name為nil,讀取同樣使用nil
let arcBook2 = Book2.read(name: nil)let arr = Book3.read(name: "book3")
刪除數(shù)據(jù):
Book1.delete(name: nil)
附加功能:歸檔字段忽略
/** 歸檔字段忽略 *///不歸檔模型中的icon字段func ignoreCodingPropertiesForCoding() -> [String]? { return ["icon"]}
,雖然MJExtension-Swift與MJExtension有著相差無異的功能,但是它們兩個(gè)的底層差別甚多??赡艽蠹矣X得在反射這方面它們體現(xiàn)出的功能效果是一樣的,但其實(shí)它們的基本代碼并無相同之處。不過對(duì)于一鍵互轉(zhuǎn)字典-模型來說,它們都是基于反射功能上實(shí)現(xiàn)的。
(2)雖然OC中的Runtime在Swift中經(jīng)測(cè)試發(fā)現(xiàn)可用,但在Swift中更多的是叫Reflect反射,所以Runtime在Swift中并不是很好用。
(3)值得注意的是Swift有全名空間,所以是不需要前綴的,但是將框架命名為CFRuntime是因?yàn)闆]有把使用OC的習(xí)慣改正過來,而OC的Runtime特性個(gè)人比較喜歡,就用了Runtime,而非Swift中的Reflect。
(4)它并不支持Swfit中的結(jié)構(gòu)體噢,兩點(diǎn)原因: 結(jié)構(gòu)體主要用于數(shù)據(jù)結(jié)構(gòu),是值類型,大型數(shù)據(jù)使用引用類型的類更好。 從繼承的角度來說,繼承自NSObject,就已經(jīng)說明問題。
寫出這套框架是由于個(gè)人對(duì)于MJExtension太過依賴,但是公司的項(xiàng)目已經(jīng)全部Swift化,所以只好抓緊時(shí)間在參考大量資料和綜合了MJExtension理念的情況下寫出來,該框架的API與MJExtension保持高度一致,如果你會(huì)使用MJExtension,那么上手CFRuntime基本沒多大問題。