关于模型嵌套,这里分享一个小技巧
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
}
}