• 很多时候我们需要把从服务器端请求下来的数据成model类,今天就介绍一下如何利用runtime实现字典转模型1、首先先建一个model类class Person:NSObject {  var name:String?  var age:NSNumber? } 2、为NSObject...

    很多时候我们需要把从服务器端请求下来的数据转成model类,今天就介绍一下如何利用runtime实现字典转模型

    1、首先先建一个model类

    class Person:NSObject { 
        var name:String?
        var age:NSNumber?
    }

    2、为NSObject创建一个extension,在其中实现字典转模型

    主要分为一下几步

    (1)获取所有的属性的名字

    (2)通过属性的名字去字典里取值

    (3)用KVC为model类赋值

    extension NSObject{
        class func objectWithKeyValues(keyValues:NSDictionary) -> AnyObject{
            let model = self.init()
            //存放属性的个数
            var outCount:UInt32 = 0
            //获取所有的属性
            let properties = class_copyPropertyList(self.classForCoder(), &outCount)
            //遍历属性
            for var i = 0;i 

    3、测试结果

    测试结果
    但是有时候我们经常会遇到这样的情况model类继承自父类,比如

    class Person:NSObject {
        var name:String?
        var age:NSNumber?
    }
    class Student:Person{
        var number:String?
        var score:NSNumber?
    }
    Student类继承自Person类我们也要为Student类中父类的属性赋值,也就是说我们在遍历属性的同时也要为父类的属性 ###4、遍历父类中得属性 在这种情况下我改变了一下思路,在获取属性的同时不在用KVC直接赋值,而是把获取的属性存起来,得到所有的属性之后在进行赋值 把扩展中得代码改造之后如下
    extension NSObject{
        class func objectWithKeyValues(keyValues:NSDictionary) -> AnyObject{
            let model = self.init()
            //获取所有的属性
            let properties = self.allProperties()
            if let _ = properties{
                for property in properties!{
                    if let value = keyValues[property.propertyNmae]{
                        //为model类赋值
                        model.setValue(value, forKey: property.propertyNmae as String)
                    }
                }
            }
            return model
        }
        class func allProperties() -> [LKKProperty]?{
            let className = NSString(CString: class_getName(self), encoding: NSUTF8StringEncoding)
                if let _ = NSString(CString: class_getName(self), encoding: NSUTF8StringEncoding){
                    //不用为NSObject的属性赋值
                    if className!.isEqualToString("NSObject"){
                        return nil
                    }
                }else{
                    return nil
                }
                var outCount:UInt32 = 0
                //所有属性LKKProperty里面放着存放这个属性
                var propertiesArray = [LKKProperty]()
                let properties = class_copyPropertyList(self.classForCoder(),&outCount)
                //获取父类的所有属性
                let superM = self.superclass()?.allProperties()
                if let _ = superM{
                    //把父类中得所有属性添加进去
                    propertiesArray += superM!
                }
                //遍历自己的属性添加进去
                for var i = 0;i 

    5、我们还经常遇到这种情况,类型嵌套,比如Person类里面还有一个Card类代表着我们的身份信息,我们在赋值的时候也想直接把Card的所有属性都能直接弄好,也就是说我们在遍历属性

    思路如下,在获取属性的过程中判断是否属于Foundtation框架,如果是直接赋值,如果不是就获取这个类的所有属性,对这个类的属性进行赋值,然后把Card这个类的对象赋值给Person这个类的对象,修改代码如下。

    class LKKProperty{
        //属性名字
        var propertyNmae:NSString!
        //属性
        var property:objc_property_t
        //属性类型
        var propertyType:LKKType!
        init(property:objc_property_t){
            self.property = property
            self.propertyNmae = NSString(CString: property_getName(property), encoding: NSUTF8StringEncoding)
            //自定义的类的描述格式为T@"_TtC15字典转模型4Card",N,&,Vcard
            //T+@+"+..+工程的名字+数字+类名+"+,+其他,而我们想要的只是类名,所以要修改这个字符串
          //获取类的描述
            var code: NSString = NSString(CString: property_getAttributes(property), encoding: NSUTF8StringEncoding)!
            //直接取出""中间的内容
            code = code.componentsSeparatedByString("\"")[1]
            let bundlePath = getBundleName()
            let range = code.rangeOfString(bundlePath)
            if range.length > 0{
                //去掉工程名字之前的内容
                code = code.substringFromIndex(range.length + range.location)
            }
            //在去掉剩下的数字
            var number:String = ""
            for char in (code as String).characters{
                if char 

    6、未完成的事情

    (1)当类的属性与字典里的key值不一定的时候,出现的情况:字典里面的key是关键字的时候

    (2)当类的属性是数组,并且数组里面要放自定义类的时候

    接着完成未完成的事情,首先当字典里的key值与属性不一致的时候,我弄了个映射

    一、解决类的属性与字典里的key值不一定的情况

    //如果需要映射关系,就让子类复写此方法,获取映射到得值
    //并且在LKKProperty这个类中添加key属性,用来取的字典Key
      func replacedKeyFromPropertyName() -> NSDictionary{
            return ["属性名字":"key名字"]
        }

    二、首先我们添加一个方法,这个方法的作用是把字典数组转成模型数组。代码如下

    //把一个字典数组转成一个模型数组
        class func objectArrayWithKeyValuesArray(array:NSArray) -> [AnyObject]{
            var temp = Array<AnyObject>()
            let properties = self.allProperties()
            for(var i = 0;i < array.count;i++){
                let keyValues = array[i] as? NSDictionary
                if (keyValues != nil){
                    let model = self.init()
                    //为每个model赋值
                    model.setValuesForProperties(properties, keyValues: keyValues!)
                    temp.append(model)
                }
            }
            return temp
        }

    三,当判断类的属性是数组的时候,通过这个方法拿到数组里面的类型

        //子类重写这个方法,说明数组里存放的对象类型
        func objectClassInArray() -> [String:String]{
            return ["属性名":"自定义类名"]
        }

    四、在赋值时若发现是数组并且是数组里装的是自定义类的时候,用二的方法得到数组对象,并且赋值

        //把一个字典里的值赋给一个对象的值
        func setValuesForProperties(properties:[LKKProperty]?,keyValues:NSDictionary){
            //判断属性数组是否存在
            if let _ = properties{
                for property in properties!{
                    //判断该属性是否属于Foundtation框架
                    if property.propertyType.isFromFoundtion {
                        if let value = keyValues[property.key]{
                            //判断是否是数组,若是数组,判断数组里装的类是否是自定义类
                            if property.propertyType.isArray && property.propertyType.arrayClass != nil && value is NSArray{
                                //把字典数组转换成模型数组
                                let temp = property.propertyType.arrayClass!.objectArrayWithKeyValuesArray(value as! NSArray)
                                //为model类赋值
                                self.setValue(temp, forKey: property.propertyNmae as String)
                            }else{
                                //为model类赋值
                                self.setValue(value, forKey: property.propertyNmae as String)
                            }
                        }
                    }else{
                        if let value = keyValues[property.key]{
                            if value is NSDictionary{
                                let subClass = property.propertyType.typeClass?.objectWithKeyValues(value as! NSDictionary)
                                //为model类赋值
                                self.setValue(subClass, forKey: property.propertyNmae as String)
                            }
                        }
                    }
                }
            }
        }

    这些内容下篇文章见,demo下载地址

    展开全文
  • 在项目中我们一般的都会碰到Json字段请求回来进行模型封装的情况,一般我们是建立一个Model然后Model里面有Json请求回来的模型字典里的各种字段,类似 name,age…….之类的。封装的时候拿到对应的模型字典,然后分别...

    在项目中我们一般的都会碰到Json字段请求回来进行模型封装的情况,一般我们是建立一个Model然后Model里面有Json请求回来的模型字典里的各种字段,类似 name,age…….之类的。封装的时候拿到对应的模型字典,然后分别进行各个字段的赋值,这个动作按照MVC的机制,一般都是放在模型里面进行处理。类似于

    -(void)toModelFromDictionary:(NSDictionary*)jsonDic{
    self.name = jsonDic[@"name"];
    self.age  = jsonDic[@"age"];
    }

    这样的话有几个弊端:
    1、后台请求回来的字典数据有可能是各种类型的,比如NSNumber,Nsstring,等,如果后台的某个字段为空,那么就会导致程序崩溃。
    2、字段比较多的话,手写字典转模型就很累人了。。

    解决办法有两个:
    1. 使用一个第三方控件,李明杰老师的MJExtension,这个控件可以做到字典转模型,模型里面还可以套结模型,也可以套接模型数组,功能比较完善和强大。
    功能点:
    JSON –> Model、Core Data Model
    JSONString –> Model、Core Data Model
    Model、Core Data Model –> JSON
    JSON Array –> Model Array、Core Data Model Array
    JSONString –> Model Array、Core Data Model Array
    Model Array、Core Data Model Array –> JSON Array
    Coding all properties of model in one line code.

    https://github.com/CoderMJLee/MJExtension

    1. 如果你不想用第三方控件,感觉自由度太低,比较受限制,那么可以尝试这种方法,使用 KVC 机制的 如下方法
    - (void)setValuesForKeysWithDictionary:(NSDictionary *)keyedValues;
    

    这个函数能够做到的事情就是把模型里对应的属性按照keyedValues里的字典键值对进行复制,完成模型的初步转化,这里注意,如果你不做任何处理,那么模型里的属性类型必须和字典里的值对应,比如字典里的时NSnumber 那么属性类型也必须是NSnumber.

    有没有办法让所有的类型统一一下,处理起来没这么麻烦要做到类型的一一对应?可以在模型里实现如下方法,系统自动调用

    // 将所有的数据转换为字符串
    -(void)setValue:(id)value forKey:(NSString *)key{
    
        if([value isKindOfClass:[NSNull class]]){
            value=nil;
        }else if([value isKindOfClass:[NSArray class]]){
        }else{
            value = [NSString stringWithFormat:@"%@",value];
        }
        [super setValue:value forKey:key];
    }
    
    // 对特殊字符 id 进行处理
    -(void)setValue:(id)value forUndefinedKey:(NSString *)key{
        NSLog(@"Undefined Key: %@", key);
    }
    

    可以封装一个BaseModel 实现上面两个方法,创建如下转模型方法

    // 字典转模型
    -(id)initWithDic:(NSDictionary *)modelDic{
    
        self = [super init];
        if(self){
            [self setValuesForKeysWithDictionary:modelDic];
        }
        return self;
    
    }

    使用的时候大概是这样:

    EmployeModel *aEmploye = [[EmployeModel alloc]initWithDic:employeeDic];
    

    如果我们还想要进行模型里的模型嵌套,或者模型里的模型数组或者其他处理怎么办?
    在EmployeModel里面复写BaseModel里面的 setValueForKey比如我的EmployeModel里面还有个times 的字典数组,数组里面又是模型,单独处理。除此之外,我们还可以进行其他的一些数据微调处理。

    - (void)setValue:(id)value forKey:(NSString *)key{
    
    //    去掉从通讯录导出来时出现的 -
        if ([key isEqualToString:@"mobile"]) {
            NSArray *arr = [(NSString *)value componentsSeparatedByString:@"-"];
            value = [arr componentsJoinedByString:@""];
        }else if([key isEqualToString:@"times"]){
    
            NSMutableArray *retArr = [NSMutableArray array];
    
            for (int i=0; i<((NSArray *)value).count; i++) {
    
                NSDictionary * aDayTimeDic = ((NSArray *)value)[i];
                TimeModel *aDayTime = [[TimeModel alloc]initWithDic:aDayTimeDic];
                [retArr addObject:aDayTime];
    
            }
            value = retArr;
        }
        [super setValue:value forKey:key];
    }
    
    展开全文
  • swift 字典转模型框架

    2016-10-13 16:41:27
    swift 字典转模型框架

     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?

    }





    展开全文
  • 我们都知道KVC 是OC NSobject特有的,之前在Swift4.0之前,继承NSobject的对象,可用动态的拿到字典调用KVC模型赋值。只是比较省事的操作,有没有定义属性,只要从写UndefinedKey这个属性即可。  还是用代码演示...

     我们都知道KVC 是OC  NSobject特有的,之前在Swift4.0之前,继承NSobject的对象,可用动态的拿到字典调用KVC给模型赋值。只是比较省事的操作,有没有定义属性,只要从写UndefinedKey这个属性即可。

     还是用代码演示比如下面一个对象,从字典赋值

    //
    //  UserAccount.swift
    //  WeiBo
    //
    //  Created by 张宇 on 2018/2/6.
    //  Copyright © 2018年 张宇. All rights reserved.
    //
    
    //
    //  用户账号Model
    //
    
    import UIKit
    
    class UserAccount: NSObject {
        
        //MARK : 存储属性
        var  access_token:String = ""
        var  expires_in:TimeInterval = 0.0
        var  uid:String?
        
        init(dict:[String:Any]){
            super.init()
            setValuesForKeys(dict)
        }
        
        override func setValue(_ value: Any?, forUndefinedKey key: String) {
            
        }
        
        override var description: String{
            return  dictionaryWithValues(forKeys: ["access_token","expires_in","uid"]).description
        }
    }
    

    3.0这样写肯定是没有错误的,但是4.0的时候你就会发现一个问题forUndefinedKey这个方法每次都会调用,然后就崩溃了。


    猜测原因:这是因为KVC是OC 的方法,OC方法和属性都需要运行时写到类对象中,swift 利用KVC设置属性需要运行时机制,swift4.0以前,编译器默认帮我们做了在对象声明前加上了@objc,4.0需要手动加上。


      //MARK : 存储属性
        @objc var  access_token:String = ""
        @objc var  expires_in:TimeInterval = 0.0
        @objc var  uid:String?

       这样就不会报错了。



    展开全文
  • 参考swift4.0字典转模型:...=====================kvc字典转模型========================= *****第一层模型 import UIKit class LYBHomeLunboModel: NSObject {  @...

    参考swift4.0字典转模型:https://www.cnblogs.com/shaoting/p/8087153.html

     

     

    =====================kvc字典转模型=========================

    
    
    *****第一层模型
    
    import UIKit
    
    
    
    class LYBHomeLunboModel: NSObject {
    
        @objc var name:String?="11"
    
         
    
        @objc var age:NSNumber?
    
        @objc var phones:[LYBPhonesModel]?
    
     init(dict:[String:Any]) {
    
            super.init()
    
             setValuesForKeys(dict)
    
        }
    
        override func setValue(_ value: Any?, forKey key: String) {
    
            
    
            if key=="phones"{
    
                let temp = value as! [AnyObject]
    
                    var resultArray = [LYBPhonesModel]()
    
                    for dict in temp {
    
                    resultArray.append(LYBPhonesModel(dict: dict as! [String : AnyObject]))
    
                
    
            }
    
                phones = resultArray
    
                return
    
                        }
    
            super.setValue(value, forKey: key)
    
        }
    
        override func setValue(_ value: Any?, forUndefinedKey key: String) {
    
        }
    
        
    
       
    
    }
    
    *****************第二层模型*********
    
    
    
    import UIKit
    
    
    
    class LYBPhonesModel: NSObject {
    
       @objc var name:String?
    
       @objc var number:String?
    
        
    
        init(dict: [String: AnyObject]) {
    
            super.init()
    
            
    
            setValuesForKeys(dict)
    
        }
    
        
    
        override func setValue(_ value: Any?, forKey key: String) {
    
            super.setValue(value, forKey: key)
    
        }
    
        override func setValue(_ value: Any?, forUndefinedKey key: String) {
    
            
    
        }
    
    }
    
    
    
    
    
    
    
    
    
    
    
    
    
    *****************
    
    
    
    //kvc
    
        func swiftkvc(){
    
         
    
    
    
     //1.这是一个JSON字符串
    
            let jsonStr = "[{\"name\": \"hangge\", \"age\": 100, \"phones\": [{\"name\": \"公司\",\"number\": \"123456\"}, {\"name\": \"家庭\",\"number\": \"001\"}]}, {\"name\": \"big boss\",\"age\": 1,\"phones\": [{ \"name\": \"公司\",\"number\": \"111111\"}]}]"
    
            
    
            //2.吧JSON字符串变成data数据
    
            if let jsonData = jsonStr.data(using: String.Encoding.utf8, allowLossyConversion: false) {
    
              
    
        //***************系统的序列化成json*************
    
                do{
    
    //                //3.吧jsondata转换成JSON对象(即字典,或字典数组)
    
                    if  let dictArr:[[String:Any]]=(tryJSONSerialization.jsonObject(with:jsonData , options: .allowFragments)as?[[String : Any]])  {
    
                        let dict:[String:Any]=dictArr[1]
    
                        let model:LYBHomeLunboModel=LYBHomeLunboModel(dict:dict)
    
                        
    
                        print("\(model.phones![0].name!)")
    
                    }
    
                }
    
            catch {
    
    
    
                }
    
            
    
    
    
        }
    
    
    

     

    ================================MJExtention桥接字典转模型================================


     

    
    ////1.这是一个JSON字符串
    
    //let jsonStr = "
    
    //[
    
    //{\"name\": \"hangge\",
    
    //\"age\": 100,
    
    //\"phones\":
    
    //    [
    
    //    {
    
    //        \"name\": \"公司\",
    
    //    \"number\": \"123456\"
    
    //
    
    //    },
    
    //    {
    
    //        \"name\": \"家庭\",
    
    //        \"number\": \"001\"
    
    //
    
    //    }
    
    //    ]
    
    //},
    
    //{
    
    //    \"name\": \"big boss\",
    
    //    \"age\": 1,
    
    //    \"phones\":
    
    //    [
    
    //    {
    
    //        \"name\": \"公司\",
    
    //    \"number\": \"111111\"
    
    //
    
    //    }
    
    //    ]
    
    //
    
    //}
    
    //    ]"
    
    
    
    #import <Foundation/Foundation.h>
    
    #import <MJExtension/MJExtension.h>
    
    @interface LYBmjextentionTofirstModel : NSObject
    
    @property(nonatomic,copy)NSString *name;
    
    @property(nonatomic,copy)NSString *age;
    
    @property(nonatomic,strong)NSArray *phones;
    
    @end
    
    
    
    ****************
    
    
    
    #import "LYBmjextentionTofirstModel.h"
    
    
    
    #import "LYBmjextentionModelTosec.h"
    
    @implementation LYBmjextentionTofirstModel
    
    + (NSDictionary *)mj_objectClassInArray
    
    
    
    {
    
        return@{@"phones" : [LYBmjextentionModelTosecclass]};
    
    }
    
    @end
    
    
    
    
    
    *******************
    
    
    
    
    
    #import <Foundation/Foundation.h>
    
    #import <MJExtension/MJExtension.h>
    
    @interface LYBmjextentionModelTosec : NSObject
    
    @property(nonatomic,copy)NSString *name;
    
    @property(nonatomic,copy)NSString *number;
    
    @end
    
    
    
    ************************
    
    
    
    
    
    
    
    #import "LYBmjextentionModelTosec.h"
    
    
    
    @implementation LYBmjextentionModelTosec
    
    
    
    @end
    
    
    
    **************************
    
    
    
    swift的桥接文件中
    
    #import <MJExtension/MJExtension.h>
    
    #import "LYBmjextentionTofirstModel.h"
    
    **************
    
    在VC中使用:
    
     //1.这是一个JSON字符串
    
            let jsonStr ="[{\"name\": \"hangge\", \"age\": 100, \"phones\": [{\"name\": \"公司\",\"number\": \"123456\"}, {\"name\": \"家庭\",\"number\": \"001\"}]}, {\"name\": \"big boss\",\"age\": 1,\"phones\": [{ \"name\": \"公司\",\"number\": \"111111\"}]}]"
    
            
    
            //2.吧JSON字符串变成data数据
    
            if let jsonData = jsonStr.data(using:String.Encoding.utf8, allowLossyConversion:false) {
    
    
    
    
    
    //**************swiftyjson*吧json的data数据序列化成json对象然后mjextention转模型****************不用担心数组越界,不用判断节点,拆包什么的
    
               
    
                do{//序列化成JSON对象
    
                    let json = try JSON(data: jsonData, options:.allowFragments)
    
                    let dict=json[0]
    
    
    
                   let fm=LYBmjextentionTofirstModel.mj_object(withKeyValues:dict)或者print(fm)
    
                    let model:LYBmjextentionTofirstModel=LYBmjextentionTofirstModel()
    
                    model.mj_setKeyValues(dict)
    
                    print(model)
    
                    print("\(model.name)")
    
                }catch{
    
                   
    
                }
    
                
    
            }
    

    ==================反射字典转模型=========

    参考:http://swift.gg/2015/11/23/swift-reflection-api-what-you-can-do/#custom_mirrors

    https://www.jianshu.com/p/3d0dba5f781a

     

    所谓反射就是可以动态获取类型、成员信息,同时在运行时(而非编译时)可以动态调用任意方法、属性等行为的特性。

    Swift的反射机制是基于一个叫Mirror的struct来实现的,其内部有如下属性和方法:

    
    let children: Children  //对象的子节点。
    
    displayStyle: Mirror.DisplayStyle?   //对象的展示风格
    
    let subjectType: Any.Type  //对象的类型
    
    func superclassMirror() -> Mirror?   //对象父类的
    
    
    
    基于上面mjextention中的模型来实现:
    
      let model:LYBmjextentionTofirstModel=LYBmjextentionTofirstModel()
    
                model.name="名字"
    
                    model.age="18"
    
                    //将model进行反射
    
                    let aMirror = Mirror(reflecting: model)
    
                    print("对象类型:\(aMirror.subjectType)")
    
                    print("对象子元素的个数:\(aMirror.children.count)")
    
                    print("对象的展示风格:\(aMirror.displayStyle)")
    
                   
    
          *******************
    
            
    

    =======================HandyJSON==============阿里巴巴出的

     

    下载地址:https://github.com/alibaba/handyjson

     

    参考:https://www.cnblogs.com/crazyacking/p/5927909.html?hmsr=toutiao.io&utm_medium=toutiao.io&utm_source=toutiao.io

    采用Swift反射+内存赋值的方式来构造Model实例,保持原汁原味的Swift类定义

    在Swift中把JSON反序列化到Model类,在HandyJSON出现以前,主要使用两种方式:

    1. 让Model类继承自NSObject,然后class_copyPropertyList()方法获取属性名作为Key,从JSON中取得Value,再通过Objective-C runtime支持的KVC机制为类属性赋值;如JSONNeverDie

    2. 支持纯Swift类,但要求开发者实现Mapping函数,使用重载的运算符进行赋值,如ObjectMapper

    这两者都有显而易见的缺点。前者要求Model继承自NSObject,非常不优雅,且直接否定了用struct来定义Model的方式;后者的Mapping函数要求开发者自定义,在其中指明每个属性对应的JSON字段名,代码侵入大,且仍然容易发生拼写错误、维护困难等问题。

    ***注意:swift4.0,在用cocoapods引入的时候,需要注明版本pod 'HandyJSON','4.0.0-beta.1'

     

    HandyJSON支持在类定义里使用各种形式的基本属性,包括可选(?),隐式解包可选(!),数组(Array),字典(Dictionary),Objective-C基本类型(NSString、NSNumber),各种类型的嵌套([Int]?、[String]?、[Int]!、...)等等

     

    使用举例:
    
    1.***********简单的json字符串(字符串中是纯json格式):
    
    
    import UIKit
    import HandyJSON
    class LYBHandyJsononeModel: HandyJSON {//模型类需要继承HandyJSON
        @objc var name:String?
        @objc var age:NSNumber?
        
     required init() {}// 如果定义是struct,连init()函数都不用声明;
    }
    
    
    
    
    使用:
    
     let jsonStr="{\"name\": \"hangge\", \"age\": 100}"
              
            //2.吧JSON字符串变成data数据
            if let jsonData = jsonStr.data(using: String.Encoding.utf8, allowLossyConversion: false) {
              
        //***************系统的序列化成json*************
                do{
    //                //3.吧jsondata转换成JSON对象(即字典,或字典数组)
                    if  let dict:[String:Any]=(try JSONSerialization.jsonObject(with:jsonData , options: .allowFragments)as?[String : Any])  {
                       let model=JSONDeserializer<LYBHandyJsononeModel>.deserializeFrom(dict: dict)
                        print((model?.name)!)
                    }
                }
            catch {
    
                }
            

    3.***************---json字符串中的最外层是数组

    import UIKit
    import HandyJSON
    class LYBHandyJsononeModel: HandyJSON {
        @objc var name:String?
        @objc var age:String?
        
     required init() {}// 如果定义是struct,连init()函数都不用声明;
    }

     

     使用:

     //1.这是一个JSON字符串,字符串中最外层是数组
            let jsonStr = "[{\"name\": \"hangge\", \"age\": 100, \"phones\": [{\"name\": \"公司\",\"number\": \"123456\"}, {\"name\": \"家庭\",\"number\": \"001\"}]}, {\"name\": \"big boss\",\"age\": 15,\"phones\": [{ \"name\": \"公司\",\"number\": \"111111\"}]}]"
            let model=JSONDeserializer<LYBHandyJsononeModel>.deserializeModelArrayFrom(json: jsonStr)
            print((model?[0]?.age)!)
    

    4.***********json字符串,最外层是数组,数组中的内容是字典

     

     

    import UIKit
    import HandyJSON
    class LYBHandyJsononeModel: HandyJSON {
        @objc var name:String?
        @objc var age:String?
        
     required init() {}// 如果定义是struct,连init()函数都不用声明;
    }
     //1.这是一个JSON字符串,字符串中最外层是数组
            let jsonStr = "[{\"name\": \"hangge\", \"age\": 100, \"phones\": [{\"name\": \"公司\",\"number\": \"123456\"}, {\"name\": \"家庭\",\"number\": \"001\"}]}, {\"name\": \"big boss\",\"age\": 15,\"phones\": [{ \"name\": \"公司\",\"number\": \"111111\"}]}]"
           

     

     

    使用:

    
     //2.吧JSON字符串变成data数据
            if let jsonData = jsonStr.data(using: String.Encoding.utf8, allowLossyConversion: false) {
              
        //***************系统的序列化成json*************
                do{
    //                //3.吧jsondata转换成JSON对象(即字典,或字典数组)
                    if  let dictArr:[[String:Any]]=(try JSONSerialization.jsonObject(with:jsonData , options: .allowFragments)as?[[String : Any]])  {
                       let model=JSONDeserializer<LYBHandyJsononeModel>.deserializeModelArrayFrom(array: dictArr)
                        print((model![0]?.name)!)
                    }
                }
            catch {
    
                }
            
     let model=JSONDeserializer<LYBHandyJsononeModel>.deserializeModelArrayFrom(array: dictArr)
                        print((model![0]?.name)!)
                    }
                }
            catch {
    
                }
            
    

    ===========字典数组转模型1=========

     /*
                 {
                 msg = "\U83b7\U53d6\U6210\U529f";
                 result =     {
                 ad =         (
                 {
                 "ad_code" = "http://www.ddb.cn/public/upload/ad/2018/07-24/f1278a99a637ff4db766e94339dec180.jpg";
                 "ad_link" = "https://mp.weixin.qq.com/s/x1JPnh5qXl0bkyvN5EcvrA";
                 "ad_name" = "\U4fe1\U7528\U5361\U57ab\U8fd8";
                 },
                 {
                 "ad_code" = "http://www.ddb.cn/public/upload/ad/2018/08-22/8b7a59c2924c1813f9e2c5895a02a226.png";
                 "ad_link" = "https://mp.weixin.qq.com/s/phLc3iHQaU6TyI6hkmfIpg";
                 "ad_name" = "\U4fe1\U7528\U5361\U529e\U7406";
                 },
                 {
                 "ad_code" = "http://www.ddb.cn/public/upload/ad/2018/11-09/52be0b76b5c4d579cbb3c88d146c6ea0.jpg";
                 "ad_link" = "https://mp.weixin.qq.com/s/sWM6q5Fi726Ruj73uFZVfg";
                 "ad_name" = "\U81ea\U5b9a\U4e49\U5e7f\U544a\U540d\U79f0";
                 }
                 );
                 };
                 status = 1;
                 }
    */
                if  ((res["result"]) != nil) {//判断res中是否存在result这个键
                let resultDict=res["result"] as! NSDictionary
                 if  ((res["ad"]) != nil) {
                    let ad:[[String:AnyObject]]=resultDict.value(forKey: "ad") as! [[String : AnyObject]]
                     print("\(ad.count)")
                   
                    let model=JSONDeserializer<LYBHomeHeaderScrollModel>.deserializeModelArrayFrom(array: ad);//字典数组转成模型数组方法一
    //                let headerScrollModel=[LYBHomeHeaderScrollModel].deserialize(from: ad)// 字典数组转换成模型数组方法二
                print("\(String(describing: model?[0]?.ad_link))")
                    }
                }else {
                    print("没有")
                }

    ============字典转模型==============

    if  ((res["result"]) != nil) {//判断res中是否存在result这个键
                let resultDict=res["result"] as? NSDictionary
                let  loginresultModel=LYBLoginResultModel.deserialize(from: resultDict)//这是根据字典转模型,还可以直接字符串转模型
                LYBLoginVC.model=loginresultModel//静态变量存储,整个程序生命周期期间且所有类中都可以用
                print("\(String(describing: loginresultModel?.token))")
            }else{
                print("没有")
            }

    ********嵌套转模型*******

     lazy var rightdata:[String:[[String:[String]]]]={
            let dataDict:[String:[[String:[String]]]]=["leftone":[["headerName":["one第一组"],"images":["icon_shot_sel","icon_shot_sel","icon_shot_sel","icon_shot_sel","icon_shot_sel","icon_shot_sel"]],["headerName":["one第二组"],"images":["comm_btn_checkmark","comm_btn_checkmark","comm_btn_checkmark","comm_btn_checkmark","comm_btn_checkmark","comm_btn_checkmark"]],["headerName":["one第三组"],"images":["comm_btn_checkmark","comm_btn_checkmark","comm_btn_checkmark","comm_btn_checkmark","comm_btn_checkmark","comm_btn_checkmark"]]],
                                                       "lefttwo":[["headerName":["two第一组"],"images":["icon_shot_sel","icon_shot_sel","icon_shot_sel","icon_shot_sel","icon_shot_sel","icon_shot_sel"]],["headerName":["two第二组"],"images":["comm_btn_checkmark","comm_btn_checkmark","comm_btn_checkmark","comm_btn_checkmark","comm_btn_checkmark","comm_btn_checkmark"]],["headerName":["two第三组"],"images":["comm_btn_checkmark","comm_btn_checkmark","comm_btn_checkmark","comm_btn_checkmark","comm_btn_checkmark","comm_btn_checkmark"]]],
                                                       "leftthree":[["headerName":["three第一组"],"images":["icon_shot_sel","icon_shot_sel","icon_shot_sel","icon_shot_sel","icon_shot_sel","icon_shot_sel"]],["headerName":["three第二组"],"images":["comm_btn_checkmark","comm_btn_checkmark","comm_btn_checkmark","comm_btn_checkmark","comm_btn_checkmark","comm_btn_checkmark"]],["headerName":["three第三组"],"images":["comm_btn_checkmark","comm_btn_checkmark","comm_btn_checkmark","comm_btn_checkmark","comm_btn_checkmark","comm_btn_checkmark"]]]
                         ]
            
            return dataDict
        }()
    
    
    *******第一层
    import UIKit
    
    class LYBTabAndCollectionConnectModel: HandyJSON {
        var leftone:[LYBrightSecModel]?
         var lefttwo:[LYBrightSecModel]?
         var leftthree:[LYBrightSecModel]?
        
        required init(){
            
        }
    }
    
    
    *******第二层
    import UIKit
    
    class LYBrightSecModel: HandyJSON {
    
        var headerName:[String]?
        var images:[String]?
        required init(){
        
        }
    }
    
    
    使用: let  modelDict=LYBTabAndCollectionConnectModel.deserialize(from: rightdata) as! LYBTabAndCollectionConnectModel
            print("\(String(describing: modelDict.leftone?.first?.images?.first))")
    

    5.*******************字典中的value是字典或者是数组(数组中的元素是字典),继续创建下一级模型

    嵌套的Model类

     

    如果Model类中的某个属性是另一个自定义的Model类,那么只要那个Model类也实现了HandyJSON协议,就一样可以转换:

     

    
    //第一层模型
    
    import UIKit
    
    import HandyJSON
    
    class LYBHandyJsononeModel: HandyJSON {
    
      var name:String?
    
    var age:String?
    
      var phones:[LYBHandyJsonSecModel]?
    
     required init() {}// 如果定义是struct,连init()函数都不用声明;
    
    }
    
    
    
    //第二层模型
    
    import UIKit
    
    import HandyJSON
    
    class LYBHandyJsonSecModel: HandyJSON {
    
        var name:String?
    
        var age:String?
    
        
    
        required init() {}// 如果定义是struct,连init()函数都不用声明;
    
    }
    
    
    
     //1.这是一个JSON字符串,字符串中最外层是数组
            let jsonStr = "[{\"name\": \"hangge\", \"age\": 100, \"phones\": [{\"name\": \"公司\",\"number\": \"123456\"}, {\"name\": \"家庭\",\"number\": \"001\"}]}, {\"name\": \"big boss\",\"age\": 15,\"phones\": [{ \"name\": \"公司\",\"number\": \"111111\"}]}]"
           
    [{\"name\": \"hangge\", \"age\": 100, \"phones\": [{\"name\": \"公司\",\"number\": \"123456\"}, {\"name\": \"家庭\",\"number\": \"001\"}]}, {\"name\": \"big boss\",\"age\": 15,\"phones\": [{ \"name\": \"公司\",\"number\": \"111111\"}]}]"
           
    

    使用:

     //2.吧JSON字符串变成data数据
    
    
            if let jsonData = jsonStr.data(using: String.Encoding.utf8, allowLossyConversion: false) {
              
        //***************系统的序列化成json*************
                do{
    //                //3.吧jsondata转换成JSON对象(即字典,或字典数组)
                    if  let dictArr:[[String:Any]]=(try JSONSerialization.jsonObject(with:jsonData , options: .allowFragments)as?[[String : Any]])  {
                      let model=JSONDeserializer<LYBHandyJsononeModel>.deserializeModelArrayFrom(array: dictArr)
                        let phones=model![0]?.phones;
                        print("\((phones![1].name)!)")
                    }
                }
            catch {
    
                }
              let model=JSONDeserializer<LYBHandyJsononeModel>.deserializeModelArrayFrom(array: dictArr)
                        let phones=model![0]?.phones;
                        print("\((phones![1].name)!)")
                    }
                }
            catch {
    
                }
    
    
    6.********************指定反序列化JSON中某个节点(指定路径转模型,可以选择有用的数组转模型,跳过无用的数据)------解析的指定路径要保证唯一性才可以;
    <span style="color:#ff0000">这是一个JSON字符串,字符串内只有字典嵌套,可以任意指定路径解析</span>

     

    有时候服务端返回给我们的JSON文本包含了大量的状态信息,和Model无关,可以指定反序列化哪个节点:

    有继承关系的Model类

    如果某个Model类继承自另一个Model类,只需要这个父Model类实现HandyJSON协议就可以:

    //第一层模型

    import UIKit

    import HandyJSON

    class LYBHandyJsononeModel: HandyJSON {

      var name:String?

    var age:String?

      var phones:LYBHandyJsonSecModel?

     required init() {}// 如果定义是struct,连init()函数都不用声明;

    }

    *******

    //第二层模型

    import UIKit

    import HandyJSON

    class LYBHandyJsonSecModel: HandyJSON {

        var name:String?

        required init() {}// 如果定义是struct,连init()函数都不用声明;

    }

     

    ***********

    //第三层模型

    import UIKit

    import HandyJSON

    class LYBthreemodel: HandyJSON {

        var age:String?

        required init() {}// 如果定义是struct,连init()函数都不用声明;

    }

     

     

    使用:

     //1.这是一个JSON字符串,字符串内只有字典嵌套,指定路径解析
            let jsonStr = "{\"name\": \"hangge\", \"age\": 100, \"phones\":{\"name\": {\"age\": 100}}}"
            let model=JSONDeserializer<LYBHandyJsononeModel>.deserializeFrom(json: jsonStr, designatedPath: "phones.name")
            print(model?.age)/1.这是一个JSON字符串,字符串内只有字典嵌套,指定路径解析
            let jsonStr = "{\"name\": \"hangge\", \"age\": 100, \"phones\":{\"name\": {\"age\": 100}}}"
            let model=JSONDeserializer<LYBHandyJsononeModel>.deserializeFrom(json: jsonStr, designatedPath: "phones.name")
            print(model?.age)


    7.**********************指定路径解析(字典的value值有数组,路径最多只能到数组的键值这里)

    //第一层模型
    import UIKit
    import HandyJSON
    class LYBHandyJsononeModel: HandyJSON {
      var name:String?
    var age:String?
      var phones:[LYBHandyJsonSecModel]?
     required init() {}// 如果定义是struct,连init()函数都不用声明;
    }
    

    //第二层模型

    import UIKit

    import HandyJSON

    class LYBHandyJsonSecModel: HandyJSON {

        var name:String?

        required init() {}// 如果定义是struct,连init()函数都不用声明;

    }

    //第三层模型

    import UIKit

    import HandyJSON

    class LYBthreemodel: HandyJSON {

        var age:String?

        required init() {}// 如果定义是struct,连init()函数都不用声明;

    }

     

     

     

      //1.这是一个JSON字符串,字典的value值是数组,指定路径解析
            let jsonStr = "{\"name\": \"hangge\", \"age\": 100, \"phones\":[{\"name\": {\"age\": 100}}]}"
            let model=JSONDeserializer<LYBHandyJsononeModel>.deserializeModelArrayFrom(json: jsonStr, designatedPath: "phones")//因为phones是数组(所以要使用deserializeModelArrayFrom()
    ),数组中元素可能有多个,无法确定唯一路径,这里只能指定到phones
            print(model)
     //1.这是一个JSON字符串,字典的value值是数组,指定路径解析
            let jsonStr = "{\"name\": \"hangge\", \"age\": 100, \"phones\":[{\"name\": {\"age\": 100}}]}"
            let model=JSONDeserializer<LYBHandyJsononeModel>.deserializeModelArrayFrom(json: jsonStr, designatedPath: "phones")//因为phones是数组(所以要使用deserializeModelArrayFrom()
    ),数组中元素可能有多个,无法确定唯一路径,这里只能指定到phones
            print(model)
    


    8.****************自定义解析方式*****************

     

     

    HandyJSON还提供了一个扩展能力,就是允许自行定义Model类某个字段的解析Key、解析方式。我们经常会有这样的需求:

    • 某个Model中,我们不想使用和服务端约定的key作为属性名,想自己定一个;
    • 有些类型如enumtuple是无法直接从JSON中解析出来的,但我们在Model类中有这样的属性;

    HandyJSON协议提供了一个可选的mapping()函数,我们可以在其中指定某个字段用什么Key、或者用什么方法从JSON中解析出它的值

    //第一层模型

    import UIKit

    import HandyJSON

    class LYBHandyJsononeModel: HandyJSON {

      var myname:String?

    var age:(String,String)?

      var phones:[LYBHandyJsonSecModel]?

     required init() {}// 如果定义是struct,连init()函数都不用声明;

        

        func mapping(mapper: HelpingMapper) {

            //指定name字段用myname去解析

           mapper.specify(property: &myname, name: "name")

            //指定age用这个方法解析返回的是元祖,age中是100/200---分成100和200组成元组

            mapper.specify(property: &age) { (rawString) -> (String, String) in

                let parentNames = rawString.split(separator: "/").map(String.init)//

                return (parentNames[0], parentNames[1])

            }

           

           

     

        }

        

    }

     

    //第二层模型

    import UIKit

    import HandyJSON

    class LYBHandyJsonSecModel: HandyJSON {

        var name:String?

        required init() {}// 如果定义是struct,连init()函数都不用声明;

    }

     

     

      //1.这是一个JSON字符串,解析的时候把100/200解析成一个元祖(100,200)
        let jsonStr = "{\"name\": \"hangge\", \"age\":\"100/200\", \"phones\":[{\"name\": {\"age\": 100}}]}"
            let model=JSONDeserializer<LYBHandyJsononeModel>.deserializeFrom(json: jsonStr, designatedPath: "")//路径是空的话,意思和不带路径的方法一个效果
            print(model?.age)解析的时候把100/200解析成一个元祖(100,200)
        let jsonStr = "{\"name\": \"hangge\", \"age\":\"100/200\", \"phones\":[{\"name\": {\"age\": 100}}]}"
            let model=JSONDeserializer<LYBHandyJsononeModel>.deserializeFrom(json: jsonStr, designatedPath: "")//路径是空的话,意思和不带路径的方法一个效果
            print(model?.age)


    9.****************

     

    展开全文
  • KVC 字典转模型构造函数 /// `重写`构造函数 /// /// - parameter dict: 字典 /// /// - returns: Person 对象 init(dict: [String: AnyObject]) { setValuesForKeysWithDictionary(dict) } 以上代码编译就会报错...
  • 为了代码可读性以及开发效率,我们往往会将数据抽象为数据模型,在开发过程中操作数据模型而不是数据本身。 在开发过程中,我们需要将key...下面我们来分别探讨一下,OC跟swift中几种主流的字典转模型方式。 1 swift...
  • 重载: 方法名相同,参数个数/参数类型不同 方法重载不仅仅局限于 init构造方法,其他的方法也同样使用 在init的构造方法中, 不需要在前面加func , 重写init需要添加关键字override ....重写是因为,系统提供的...
  • KVC简单介绍 KVC是OC特有的,KVC本质上是在运行时,动态向对象发送setValue:ForKey:方法,为对象的属性设置数值 因此,在使用KVC的方法之前,需要确保对象已经被正确实例化 在Swift中,如果属性是可选的,在初始...
  • 本篇介绍数据转模型Codable的使用,Codable是苹果自带的基于KVC编码的数据转换模型的协议。 先创建对应的model let dic = ["name":"wall" , "age":"22" , "h":...
  • swift KVC函数调用

    2018-07-25 10:41:05
    // 1 定义模型属性的时候,如果是对象,通常都是可选的(- 在需要的时候创建 - 避免写构造函数,可以简化代码) // 2 使用kvc方法之前,应该调用super.init保证对象实例化完成 class Person : NSObject { // name...
  • 2018.05.02 20:20:16字数 1,493阅读 5,017 一 简介 二 特性 ...与其他流行的Swift JSON库相比,HandyJSON的特点是,它支持纯swift类,使用也简单。它反序列化时(把JSON转换为Model)不要求Model...
  • 1.命名空间 在同一个项目中,所有的类都是共享的,可以直接访问,...Swift支持函数重载,所有构造函数都是init 作用: 分配空间,设置初始值 ** 注意 Object-c的初始化,是从类继承关系链,从父类开始逐级向子类初始化...
  • 最近项目开始转用Swift3开发,由于Swift中json(字典)转模型的选择方案较多,笔者最开始选择了HandyJSON的方案,在使用一段时间后发现当要进行某个字段取值使用时需要进行各种的转化判断,比较麻烦(但是安全、保证...
  • 开始学习iOS开发的时候,对Objective-C的消息转发机制和运行时十分不解,感觉很高深的样子,就一直没有下功夫去研究这些问题.最近看了一些资料,对这部分知识做了一些总结,分享出来供大家参考学习,若有错误请联系我更正,...
  • 需求一:将字典转换成自己需的对象,对象的属性是字典的key值,直接使用key值获取数据存在两个缺点,一是key值难以记忆,二是直接使用key值Xcode不会有智能提示,很容易导致未知的错误。使用模型时,可以直接通过点...
  • iOS开发中很多人都知道KVC ,聊到KVC大家也都知道,就是字典转模型,但是再具体聊的话,就说不太清楚了,这篇文章,准备把KVC再来了解一下; XZPerson *person = [XZPerson alloc]; person.name = @"Alan"; 在...
  • Swift4.0后,终于推出了Codable协议,可实现json数据和数据模型的相互转换。 首先来下 Codable ,它其实是一个组合协议,有 Decodable 和 Encodable 两个协议组成。 /// A type that can convert itself into ...
  • 提到字典转模型,MJExtension类似这个库,用过的就晓得成model是多么的便捷。 本文就dictionary -> model 略微介绍以下。 首先,创建一个model类。 [objc] view plain copy @interface Model...
  • swiftkvc

    2018-02-01 10:43:47
    ===========kvc KVC是OC特有的,KVC本质上是在运行时,动态向对象发送setValue:ForKey:方法,为对象的属性设置数值 因此,在使用KVC的方法之前,需要确保对象已经被正确实例化 在Swift中,如果属性是可选的...
1 2 3 4 5 ... 20
收藏数 426
精华内容 170
关键字:

kvc字典转模型 swift