1: swift 字典转模型框架
import Foundation
@objc protocol DictModelProtocol{
///自定义映射
///
/// :returns: 返回可选映射关系字典 [属性名: 自定义对象名称]
/// :class 替换成 static 是 swift 1.2 修改的
static func customClassMapping() -> [String: String]?
}
///字典转模型工具
class SwiftDictModel {
//单例,全局访问入口
static let sharedManger = SwiftDictModel()
/// 将字典转换成模型对象
///
/// :param: dict 数据字典
/// :param: cls 模型类
///
/// :returns: 实例化的类对象
func objectWithDictionary(dict:NSDictionary,cls:AnyClass) -> AnyObject?{
//1. 取出模型类的字典
let dictInfo = fullModelinfo(cls)
//实例化对象
var obj:AnyObject = cls.alloc()
//遍历模型字典,有什么属性就设置什么属性
// k 应该 和 dict 中的 key 是一致的
for (k,v) in dictInfo {
//取出字典中的内容
if let value: AnyObject? = dict[k]{
println("要设置数值的 \(value) + key \(k)")
//判断是否是自定义类
//json 反序列化的时候,如果是null 值,保存在字典中的事NSNull()
if v.isEmpty && !(value === NSNull()){
obj.setValue(value, forKey: k)
}else{
let type = "\(value!.classForCoder)"
println("\t自定义对象 \(value) \(k) \(v) ---- type \(type)")
//两种可能,字典/数组
if type == "NSDictionary"{
// value 是字典-> 将 value 的字典转换成 Info 的对象
if let subObj: AnyObject? = objectWithDictionary(value as! NSDictionary, cls: NSClassFromString(v)){
//使用kvc设置数值
obj.setValue(subObj, forKey: k)
}
}else if type == "NSArray" {
//value 是数组
//如果是数组如何处理? 遍历数组,继续处理数组中的字典
if let subObj:AnyObject? = objectWithArray(value as! NSArray, cls: NSClassFromString(v)){
obj.setValue(subObj, forKey: k)
}
}
}
}
}
println(dictInfo)
return obj
}
///将数组转换成模型字典
///
/// :parm: array 数组的描述
/// : param: cls 模型类
///
/// :returns: 模型数组
func objectWithArray(array: NSArray, cls: AnyClass) -> [AnyObject]? {
//创建一个数组
var result = [AnyObject]()
//1.遍历数组
//可能存在什么类型? 字典/数组
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] {
// 判断类信息是否已经被缓存
if let cache = modelCache["\(cls)"] {
println("\(cls)已经被缓存")
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]{
// 判断类信息是否已经被缓存
if let cache = modelCache["\(cls)"] {
println("\(cls)已经被缓存")
return cache
}
var mapping: [String:String]?
if cls.respondsToSelector("customClassMapping"){
println("实现了协议")
//调用协议方法,获取自定义对象映射关系字典
mapping = cls.customClassMapping()
println(mapping)
}
//获取累的属性
var count: UInt32 = 0
let ivars = class_copyIvarList(cls, &count)
println("有\(count)属性")
// // 定义一个类属性的字典:[属性的名字,自定对象的名称/“”]
var dictInfo = [String: String]()
for i in 0..<count {
//检索数组下标只能,用Int
let ivar = ivars[Int(i)]
//UInt8 = char, c语言的字符串
let cname = ivar_getName(ivar)
//将c 语言字符串转换成 swift 的String
let name = String.fromCString(cname)!
//println(name)
let type = mapping?[name] ?? ""
//设置字典
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)
}
}
}
2
import Foundation
@objc public protocol DictModelProtocol {
static func customClassMapping() -> [String: String]?
}
/// 字典转模型管理器
public class DictModelManager {
private static let instance = DictModelManager()
/// 全局统一访问入口
public class var sharedManager: DictModelManager {
return instance
}
/// 字典转模型
/// - parameter dict: 数据字典
/// - parameter cls: 模型类
///
/// - returns: 模型对象
public func objectWithDictionary(dict: NSDictionary, cls: AnyClass) -> AnyObject? {
// 动态获取命名空间
let ns = NSBundle.mainBundle().infoDictionary!["CFBundleExecutable"] as! String
// 模型信息
let infoDict = fullModelInfo(cls)
let obj: AnyObject = (cls as! NSObject.Type).init()
autoreleasepool {
// 3. 遍历模型字典
for (k, v) in infoDict {
if k == "desc" {
let newValue = dict["description"] as? String
obj.setValue(newValue, forKey: "desc")
}
if let value: AnyObject = dict[k] {
if v.isEmpty {
if !(value === NSNull()) {
if k == "number" && ScreenWidth < 375 {
if let vav: String = value as? String {
obj.setValue(Int(vav)!, forKey: k)
}
} else {
obj.setValue(value, forKey: k)
}
}
} else {
let type = "\(value.classForCoder)"
if type == "NSDictionary" {
if let subObj: AnyObject = objectWithDictionary(value as! NSDictionary, cls: NSClassFromString(ns + "." + v)!) {
obj.setValue(subObj, forKey: k)
}
} else if type == "NSArray" {
if let subObj: AnyObject = objectsWithArray(value as! NSArray, cls: NSClassFromString(ns + "." + v)!) {
obj.setValue(subObj, forKey: k)
}
}
}
}
}
}
return obj
}
/// 创建自定义对象数组
///
/// - parameter NSArray: 字典数组
/// - parameter cls: 模型类
///
/// - returns: 模型数组
public func objectsWithArray(array: NSArray, cls: AnyClass) -> NSArray? {
var list = [AnyObject]()
autoreleasepool { () -> () in
for value in array {
let type = "\(value.classForCoder)"
if type == "NSDictionary" {
if let subObj: AnyObject = objectWithDictionary(value as! NSDictionary, cls: cls) {
list.append(subObj)
}
} else if type == "NSArray" {
if let subObj: AnyObject = objectsWithArray(value as! NSArray, cls: cls) {
list.append(subObj)
}
}
}
}
if list.count > 0 {
return list
} else {
return nil
}
}
/// 模型转字典
///
/// - parameter obj: 模型对象
///
/// - returns: 字典信息
public func objectDictionary(obj: AnyObject) -> [String: AnyObject]? {
// 1. 取出对象模型字典
let infoDict = fullModelInfo(obj.classForCoder)
var result = [String: AnyObject]()
// 2. 遍历字典
for (k, v) in infoDict {
var value: AnyObject? = obj.valueForKey(k)
if value == nil {
value = NSNull()
}
if v.isEmpty || value === NSNull() {
result[k] = value
} else {
let type = "\(value!.classForCoder)"
var subValue: AnyObject?
if type == "NSArray" {
subValue = objectArray(value! as! [AnyObject])
} else {
subValue = objectDictionary(value!)
}
if subValue == nil {
subValue = NSNull()
}
result[k] = subValue
}
}
if result.count > 0 {
return result
} else {
return nil
}
}
/// 模型数组转字典数组
///
/// - parameter array: 模型数组
///
/// - returns: 字典数组
public func objectArray(array: [AnyObject]) -> [AnyObject]? {
var result = [AnyObject]()
for value in array {
let type = "\(value.classForCoder)"
var subValue: AnyObject?
if type == "NSArray" {
subValue = objectArray(value as! [AnyObject])
} else {
subValue = objectDictionary(value)
}
if subValue != nil {
result.append(subValue!)
}
}
if result.count > 0 {
return result
} else {
return nil
}
}
// MARK: - 私有函数
/// 加载完整类信息
///
/// - parameter cls: 模型类
///
/// - returns: 模型类完整信息
func fullModelInfo(cls: AnyClass) -> [String: String] {
// 检测缓冲池
if let cache = modelCache["\(cls)"] {
return cache
}
var currentCls: AnyClass = cls
var infoDict = [String: String]()
while let parent: AnyClass = currentCls.superclass() {
infoDict.merge(modelInfo(currentCls))
currentCls = parent
}
// 写入缓冲池
modelCache["\(cls)"] = infoDict
return infoDict
}
/// 加载类信息
///
/// - parameter cls: 模型类
///
/// - returns: 模型类信息
func modelInfo(cls: AnyClass) -> [String: String] {
// 检测缓冲池
if let cache = modelCache["\(cls)"] {
return cache
}
// 拷贝属性列表
var count: UInt32 = 0
let properties = class_copyPropertyList(cls, &count)
// 检查类是否实现了协议
var mappingDict: [String: String]?
if cls.respondsToSelector("customClassMapping") {
mappingDict = cls.customClassMapping()
}
var infoDict = [String: String]()
for i in 0..<count {
let property = properties[Int(i)]
// 属性名称
let cname = property_getName(property)
let name = String.fromCString(cname)!
let type = mappingDict?[name] ?? ""
infoDict[name] = type
}
free(properties)
// 写入缓冲池
modelCache["\(cls)"] = infoDict
return infoDict
}
/// 模型缓冲,[类名: 模型信息字典]
var modelCache = [String: [String: String]]()
}
extension Dictionary {
/// 将字典合并到当前字典
mutating func merge<K, V>(dict: [K: V]) {
for (k, v) in dict {
self.updateValue(v as! Value, forKey: k as! Key)
}
}
}
import UIKit
class MainAD: NSObject, DictModelProtocol {
//遵守协议DictModelProtocol
var code: Int = -1
var msg: String?
var data: AD?
class func loadADData(completion:(data: MainAD?, error: NSError?) -> Void) {
let path = NSBundle.mainBundle().pathForResource("AD", ofType: nil)
let data = NSData(contentsOfFile: path!)
if data != nil {
let dict: NSDictionary = (try! NSJSONSerialization.JSONObjectWithData(data!, options: .AllowFragments)) as! NSDictionary
//得到字典转模型管理器的对象
let modelTool = DictModelManager.sharedManager
let data = modelTool.objectWithDictionary(dict, cls: MainAD.self) as? MainAD
completion(data: data, error: nil)
}
}
//映射关系
static func customClassMapping() -> [String : String]? {
return ["data" : "\(AD.self)"]
}
}
class AD: NSObject {
var title: String?
var img_name: String?
var starttime: String?
var endtime: String?
}