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