字典转模型
用模型取代字典的好处
什么是模型
- 专门用来存放数据的对象
- 一般都是一些直接继承自
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/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此字段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权利
愿你求知如饥,愿你虚心若愚