import Foundation
@objc protocol DictModelProtocol{
///自定義映射
///
/// :returns: 返回可選映射關(guān)系字典 [屬性名: 自定義對象名稱]
/// :class 替換成 static 是 swift 1.2 修改的
static func customClassMapping() -> [String: String]?
}
///字典轉(zhuǎn)模型工具
class SwiftDictModel {
//單例录粱,全局訪問入口
static let sharedManger = SwiftDictModel()
/// 將字典轉(zhuǎn)換成模型對象
///
/// :param: dict 數(shù)據(jù)字典
/// :param: cls 模型類
///
/// :returns: 實(shí)例化的類對象
func objectWithDictionary(dict:NSDictionary,cls:AnyClass) -> AnyObject?{
//1. 取出模型類的字典
let dictInfo = fullModelinfo(cls)
//實(shí)例化對象
var obj:AnyObject = cls.alloc()
//遍歷模型字典房交,有什么屬性就設(shè)置什么屬性
// k 應(yīng)該 和 dict 中的 key 是一致的
for (k,v) in dictInfo {
//取出字典中的內(nèi)容
if let value: AnyObject? = dict[k]{
println("要設(shè)置數(shù)值的 \(value) + key \(k)")
//判斷是否是自定義類
//json 反序列化的時(shí)候撒顿,如果是null 值,保存在字典中的事NSNull()
if v.isEmpty && !(value === NSNull()){
obj.setValue(value, forKey: k)
}else{
let type = "\(value!.classForCoder)"
println("\t自定義對象 \(value) \(k) \(v) ---- type \(type)")
//兩種可能虐急,字典/數(shù)組
if type == "NSDictionary"{
// value 是字典-> 將 value 的字典轉(zhuǎn)換成 Info 的對象
if let subObj: AnyObject? = objectWithDictionary(value as! NSDictionary, cls: NSClassFromString(v)){
//使用kvc設(shè)置數(shù)值
obj.setValue(subObj, forKey: k)
}
}else if type == "NSArray" {
//value 是數(shù)組
//如果是數(shù)組如何處理? 遍歷數(shù)組虽风,繼續(xù)處理數(shù)組中的字典
if let subObj:AnyObject? = objectWithArray(value as! NSArray, cls: NSClassFromString(v)){
obj.setValue(subObj, forKey: k)
}
}
}
}
}
println(dictInfo)
return obj
}
///將數(shù)組轉(zhuǎn)換成模型字典
///
/// :parm: array 數(shù)組的描述
/// : param: cls 模型類
///
/// :returns: 模型數(shù)組
func objectWithArray(array: NSArray, cls: AnyClass) -> [AnyObject]? {
//創(chuàng)建一個(gè)數(shù)組
var result = [AnyObject]()
//1.遍歷數(shù)組
//可能存在什么類型温鸽? 字典/數(shù)組
for value in array{
let type = "\(value.classForCoder)"
if type == "NSDictionary"{
if let subObj:AnyObject = objectWithDictionary(value as! NSDictionary, cls: cls){
result.append(subObj)
}
}else if type == "NSArray"{
if let subObj: AnyObject = objectWithArray(value as! NSArray, cls: cls){
result.append(subObj)
}
}
}
return result
}
/// 緩存字典 格式[類名:模型字典瓤鼻, 類名2:模型字典]
var modelCache = [String:[String:String]]()
/// 獲取模型類的完整信息
///
///: parm:cls 模型類
func fullModelinfo(cls:AnyClass)-> [String: String] {
// 判斷類信息是否已經(jīng)被緩存
if let cache = modelCache["\(cls)"] {
println("\(cls)已經(jīng)被緩存")
return cache
}
var currentCls: AnyClass = cls
//模型字典
var dictInfo = [String:String]()
while let parent:AnyClass = currentCls.superclass(){
//取出并且拼接 currentCls 的模型字典
dictInfo.merge(modelInfo(currentCls))
currentCls = parent
println(parent)
}
// 將模型信息寫入緩存
modelCache["\(cls)"] = dictInfo
println(dictInfo)
return dictInfo
}
//獲取給定類的信息
func modelInfo(cls:AnyClass) -> [String: String]{
// 判斷類信息是否已經(jīng)被緩存
if let cache = modelCache["\(cls)"] {
println("\(cls)已經(jīng)被緩存")
return cache
}
var mapping: [String:String]?
if cls.respondsToSelector("customClassMapping"){
println("實(shí)現(xiàn)了協(xié)議")
//調(diào)用協(xié)議方法秉版,獲取自定義對象映射關(guān)系字典
mapping = cls.customClassMapping()
println(mapping)
}
//獲取累的屬性
var count: UInt32 = 0
let ivars = class_copyIvarList(cls, &count)
println("有\(zhòng)(count)屬性")
// // 定義一個(gè)類屬性的字典:[屬性的名字,自定對象的名稱/“”]
var dictInfo = [String: String]()
for i in 0..<count {
//檢索數(shù)組下標(biāo)只能茬祷,用Int
let ivar = ivars[Int(i)]
//UInt8 = char, c語言的字符串
let cname = ivar_getName(ivar)
//將c 語言字符串轉(zhuǎn)換成 swift 的String
let name = String.fromCString(cname)!
//println(name)
let type = mapping?[name] ?? ""
//設(shè)置字典
dictInfo[name] = type
}
free(ivars)
// 將模型信息寫入緩存
modelCache["\(cls)"] = dictInfo
return dictInfo
}
}
extension Dictionary{
mutating func merge<K, V>(dict:[K:V]){
for (k,v) in dict{
//字典的分類法清焕, 如果要使用 updateValue 需要明確的指定類型
self.updateValue(v as! Value, forKey: k as! Key)
}
}
}