模型嵌套

关于模型嵌套,这里分享一个小技巧

1 根据里面的字典数据,建立对应的模型数据
2 加载数据,字典转模型

  2.1 不要考虑模型嵌套的问题
  2.2 只需要考虑哪个数组里面存放的是字典数据
  2.3 接下来需要考虑,对应的字典数组在哪个类中
  2.4 只需要来到对应的类中,重写setter方法
  2.5 在这里面实现字典转模型

至于为什么是写在setter方法中:

是因为当第一次进行字典转模型时,是调用了该类自身成员属性的setter方法
(KVC->点语法->setter方法(属性中包含第二层模型类对象))
这样可以确保在创建出第二层模型类对象时第一时间将数据彻底转换成模型数据
如果写在getter方法中,无法保证第一时间将数据转换为模型数据
一旦类型不匹配时,使用就会出错

接下来介绍两种模型嵌套的实现思路:

KVC,重写setValue forKey

首先分别为字典数据创建模型,实现一个KVC构造函数(OC下提供对象、类方法或只提供一个类方法),以Swift为例

init(dict: [String: AnyObject]) {
        super.init()
        setValuesForKeysWithDictionary(dict)
    }

在这个模型类下,又嵌套了一个字典属性,将字典属性声明为一个模型类的可选项(JSUserInfoModel为第二层模型类)

var user: JSUserInfoModel?

拦截KVC,当发现为user这个属性赋值时,手动完成字典转模型
因为重写了setValue forKey方法,系统不再自动完成字典转模型,所以如果是其他属性,调用父类方法,在该类下完成字典转模型

    override func setValue(value: AnyObject?, forKey key: String) {
        
        if key == "user" {
            
            guard let val = value as? [String: AnyObject] else {
                print("可选值不存在或者不能转成字典")
                return
            }
            user = JSUserInfoModel(dict: val)
            
        }else {
            
            super.setValue(value, forKey: key)
        }
    }

为了避免KVC报错,还需空实现setValue forUndefinedKey方法

override func setValue(value: AnyObject?, forUndefinedKey key: String) {
        
    }
重写Setter方法:

第一步同样是先根据字典数据创建模型类,提供KVC构造函数
在模型类中声明字典数据时,使用字典类型进行声明

//字典数据
var user: [String: AnyObject]?

在模型类下额外添加一个模型属性

//模型数据
var _user: JSUserInfoModel?

因为KVC底层也相当于调用了点语法--> Setter方法,所以在字典树型的didSet方法中手动实现字典转模型(赋值给专门的模型属性)

var user: [String: AnyObject]?{
        didSet{
            //字典转模型
            if let u = user {
                _user = JSUserInfoModel(dict: u)
                
            }
        }
    }

总结:
在分发数据时,使用额外声明的模型属性赋值即可,两种方式,此方式的缺点就是又额外声明了一个属性,执行了两次KVC函数,效率可能不如重写setValue forKey判断key值的方式.
另外在OC下,id为系统关键字,如果遇到了字段中包含id标识,往往需要自定义一个属性名,此时就可以通过重写setValue forKey的方式进行判断进行字典转模型

示例代码:

class JSStatusModel: NSObject {
    
    //微博来源
    var source: String?
    //微博信息内容
    var text: String?
    //微博创建时间
    var created_at: String?
    //微博信息内容
    var id: Int64 = 0
    //被转发的原微博信息字段,当该微博为转发微博时返回
    var retweeted_status: JSStatusModel?
    
    //用户信息(模型嵌套方式一)
    var user: JSUserInfoModel?
    
    //模型数据(模型嵌套方式二)
    //    var _user: JSUserInfoModel?
//    var user: [String: AnyObject]?{
//        didSet{
//            //字典转模型
//            if let u = user {
//                _user = JSUserInfoModel(dict: u)
//                
//            }
//        }
//    }

    //KVC构造函数
    init(dict: [String: AnyObject]) {
        super.init()
        setValuesForKeysWithDictionary(dict)
    }
    
    //(模型嵌套方式一)
    override func setValue(value: AnyObject?, forKey key: String) {
        
        if key == "user" {
            
            guard let val = value as? [String: AnyObject] else {
                print("可选值不存在或者不能转成字典")
                return
            }
            user = JSUserInfoModel(dict: val)
            
        }else {
            
            super.setValue(value, forKey: key)
        }
    }
    
    override func setValue(value: AnyObject?, forUndefinedKey key: String) {
        
    }
    override var description: String{
        let keys = ["source","created_at","text","id"]
        return dictionaryWithValuesForKeys(keys).description
    }

}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 对于从事 iOS 开发人员来说,所有的人都会答出【runtime 是运行时】什么情况下用runtime?大部分人能...
    梦夜繁星阅读 3,751评论 7 64
  • *面试心声:其实这些题本人都没怎么背,但是在上海 两周半 面了大约10家 收到差不多3个offer,总结起来就是把...
    Dove_iOS阅读 27,263评论 30 472
  • 转至元数据结尾创建: 董潇伟,最新修改于: 十二月 23, 2016 转至元数据起始第一章:isa和Class一....
    40c0490e5268阅读 1,853评论 0 9
  • 源于一丝久存的念想, 忘却年龄, 我开了叫尚谷的道场; 再一次清零, 走商谷, 悄悄赶场。 挥一挥手, 看前路崎岖...
    悟实阅读 180评论 0 0
  • 2017/05/21 (73-216) 周日 晴 #to do list# 1、TEM8✅ 2、视频8✅ 3、高英...
    征人随说阅读 181评论 0 0