字典转模型

用模型取代字典的好处

什么是模型

  • 专门用来存放数据的对象
  • 一般都是一些直接继承自NSObject的纯对象
  • 内部会提供一些属性来存放数据

使用字典的弊端

  • 一般情况下,设置数据和取出数据都使用“字符串类型的key”,编写这些key时,编辑器没有智能提示,需要手敲
dict[@"name"] = @"Jack"; // 赋值
NSString *name = dict["@name"]; // 取值
  • 手敲字符串key时容易写错
  • key如果写错了,编译器不会有任何警告和报错,造成设错数据或取错数据。

使用模型的好处

  • 所谓模型,其实就是数据模型,专门用来存放数据对象,用它来标识数据会更加专业
  • 模型设置数据和取出数据都是通过它的属性,属性名如果写错了,编译器会马上报错,由此保证了数据的正确性
  • 使用模型访问属性时,编译器会提供一系列的提示,提高编码效率
app.name = @"Jack"; // 赋值
NSString *name = app.name; // 取值

字典转模型

首先创建一个模型

  • 这里创建一个名叫WXDShops的模型
  • 在模型的.h文件中声明两个属性
/** 商品名称  */
@property(nonatomic,strong) NSString *name;
/** 图标*/
@property(nonatomic,strong) NSString *icon;

在viewController.m文件中使用

  • 先import进来
  • 修改前代码:
NSDictionary *dict = _shops[index];
img.image = [UIImage imageNamed:dict[@"icon"]];
wLabel.text = dict[@"name"];
  • 修改后代码:
NSDictionary *dict = _shops[index];
WXDShops *shop = [[WXDShops alloc] init];
shop.name = dict[@"name"];
shop.icon = dict[@"icon"];
img.image = [UIImage imageNamed:shop.icon];
wLabel.text = shop.name;
这样看代码似乎变多了,但是会一劳永逸,以后再用,直接用“shop.***”就出来了。

代码优化

以上代码都是写在控制器中的,但是控制器“知道的太多,会死的很惨”!

  • 只要模型里面的数据发生了改变,控制器里所有字典转模型的代码都要改
  • 只要字典里的key值有改动,控制器里的字典转模型的也要改
  • 模型不一定是用在一个控制器里,多个控制器用到模型,一旦改动,所有的都要改

因此以上字典转模型的过程最好封装在模型内部

并且模型应该提供一个可以传入字典的构造方法

  • 提供一个initWithDict的构造方法,在初始化的时候就将数据赋给模型
-(id)initWithDict:(NSDictionary *)dict {
    if (self = [super init]) {
        self.name = dict[@"name"];
        self.icon = dict[@"icon"];
    }
    return self;  
}

  • 同时提供一个以类名开头的类方法
+(id)shopWithDict:(NSDictionary *)dict {
    return [[self alloc] initWithDict:dict];
}
以类名开头来命名是遵循了苹果官方的原则
  • 这时上面的代码可以优化为:
NSDictionary *dict = _shops[index];
WXDShops *shop = [[WXDShops alloc] initWithDict:dict];
//WXDShops *shop = [WXDShop shopWithDict:dict];
img.image = [UIImage imageNamed:shop.icon];
wLabel.text = shop.name;
  • 想要让字典转模型的代码也是只加载一次,因此将字典转模型代码放在懒加载中
-(NSArray *)shops {
    if (_shops == nil) {
        //加载一个字典数组
        NSArray *dictArray = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"shops" ofType:@"plist"]];
        
        NSMutableArray *shopArray = [NSMutableArray array];
        for (NSDictionary *dict in dictArray) {
            WXDShops *shop = [WXDShops shopWithDict:dict];
            [shopArray addObject:shop];
        }
        _shops = shopArray;
    }
    return _shops;  
}
  • 这样,前面优化的代码前两行可更改为一行:
WXDShops *shop = self.shops[index];
这样,在加载数据的那一刻,转模型已经转完了,且只加载了一次

instancetype

  • instancetype在类型表示上,跟id一样,可以表示任何对象类型
  • instancetype只能用在返回值类型上,不能像id一样用在参数类型上
  • instancetype比id多一个好处:编译器会检测instancetype的真实类型

因此以后的id返回类型都写成instancetype类型

类前缀

  • 使用Objective-C开发iOS程序时,最好在每个类前面加一个前缀
  • 目的是防止N个人开发了一样的类,冲突了
  • 比如JakeWill、KateRoom在同一个项目中都开发了Button类,这样的程序是不能运行起来的
  • 解决方案:JakeWill的类名叫JWButton,KateRoom的类名叫KRButton
  • 但是每次新建类的时候,都手写前缀很麻烦,能不能让前缀可以自动生成呢?看下图

自动生成类前缀方法的图片

作者:黎明豌豆
出处:http://www.cnblogs.com/PeaZora/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此字段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权利

posted @ 2016-11-09 21:42  窝窝小  阅读(416)  评论(0编辑  收藏  举报