上篇文章,我们介绍了使用plist文件加载字典数据,用字典来存储数据,用键值对来存储数据,是NSDictionary类型(坏处:容易写错,不容易调试)
我们可以使用模型来存储数据,也就是将要说的字典转模型.
字典:用来存储数据,用键值对来存储数据,是NSDictionary类型(坏处:容易写错,不容易调试)
模型:用来存储数据,用属性来存储数据,好处:(有提示,不容易写错)
字典转化成模型:一个字典转换成一个模型,把字典的键值对转换的模型的属性
模型的建立:模型是一个纯洁的object对象,里面放着是属性,属性的类型和名称有字典中的键值对的key确定,key值类型是什么类型模型中属性就是什么类型,key值的名字是什么模型的 的名字就是什么
转化过程:把字典中的键值对中的value值赋值给模型中的属性
通过用for循环遍历字典数组,把每一个字典中的键值对转换成模型的属性。
字典转模型的好处:
(1)降低代码的耦合度
(2)所有字典转模型部分的代码统一集中在一处处理,降低代码出错的几率
(3)在程序中直接使用模型的属性操作,提高编码效率
(4)调用方不用关心模型内部的任何处理细节
字典转模型的注意点:
模型应该提供一个可以传入字典参数的构造方法
- (instancetype)initWithDict:(NSDictionary *)dict;
+ (instancetype)xxxWithDict:(NSDictionary *)dict;
提示:在模型中合理地使用只读属性,可以进一步降低代码的耦合度。
附上改进后的源码:
KZApp.h
1 // 2 // KZApp.h 3 // UI基础-02-05-12 4 // 5 // Created by hukezhu on 15/5/12. 6 // 7 // 8 9 #import <Foundation/Foundation.h> 10 11 @interface KZApp : NSObject 12 /** 13 * 图片名称 14 */ 15 @property(nonatomic,copy)NSString *icon; 16 /** 17 * 图片描述 18 */ 19 @property(nonatomic,copy)NSString *desc; 20 21 /** 22 * 通过字典来初始化对象 23 * 24 * @param dict 字典对象 25 * 26 * @return 已经初始化完毕的模型对象 27 */ 28 -(instancetype)initWithDict:(NSDictionary *)dict; 29 +(instancetype)appWithApp:(NSDictionary *)dict; 30 @end
KZApp.m
1 // 2 // KZApp.m 3 // UI基础-02-05-12 4 // 5 // Created by hukezhu on 15/5/12. 6 // 7 // 8 9 #import "KZApp.h" 10 11 @implementation KZApp 12 //对象方法 13 -(instancetype)initWithDict:(NSDictionary *)dict{ 14 15 if(self = [super init]){ 16 17 //将字典的所有属性都赋值给模型 18 self.icon = dict[@"icon"]; 19 self.desc = dict[@"desc"]; 20 } 21 return self; 22 } 23 //类方法 24 +(instancetype)appWithApp:(NSDictionary *)dict{ 25 26 return [[self alloc]initWithDict:dict]; 27 } 28 @end
ViewController.m
1 // 2 // ViewController.m 3 // 01-图片浏览器1 4 // 5 // Created by hukezhu on 15/5/12. 6 // 7 // 8 9 #import "ViewController.h" 10 #import "KZApp.h" 11 //#define icon @"icon" 12 //#define desc @"desc" 13 14 @interface ViewController () 15 /** 界面上最上面显示索引的label*/ 16 @property (weak, nonatomic) IBOutlet UILabel *noLabel; 17 /** 显示图片的控件*/ 18 @property (weak, nonatomic) IBOutlet UIImageView *iconView; 19 /** 描述图片内容的label*/ 20 @property (weak, nonatomic) IBOutlet UILabel *descLabel; 21 /** 22 * 左边按钮的属性,用来控制按钮的不可用状态 23 */ 24 @property (weak, nonatomic) IBOutlet UIButton *left; 25 /** 26 * 右边按钮的属性,用来控制按钮的不可用状态 27 */ 28 @property (weak, nonatomic) IBOutlet UIButton *right; 29 /** 30 * 索引,记录位置 31 */ 32 @property (nonatomic ,assign)int index; 33 /** 34 * 存储数据的数组 35 */ 36 @property (nonatomic,strong)NSArray *images; 37 /** 38 * 上一张的点击响应方法 39 */ 40 - (IBAction)previous; 41 /** 42 * 下一张的点击响应方法 43 */ 44 - (IBAction)next; 45 @end 46 47 @implementation ViewController 48 49 - (void)viewDidLoad { 50 [super viewDidLoad]; 51 //首先将当前计数器设置为-1,然后再调用next方法,即可显示首页面. 52 //self.index = -1; 53 //[self next]; 54 [self move]; 55 } 56 //引入懒加载的概念,重写数组的get方法.当数据用到时再进行加载,好处是提高性能 57 -(NSArray *)images{ 58 59 //首先判断images是否存在数据,不存在则创建 60 //注意此处不能使用self.images,因为同是get方法,会死循环 61 if(_images == nil){ 62 //获得plist的全路径 63 NSString *path = [[NSBundle mainBundle]pathForResource:@"images.plist" ofType:nil]; 64 //加载数组 65 NSArray *dictArray = [NSArray arrayWithContentsOfFile:path]; 66 //将dictarray里面的所有字典转换成模型对象,放到新的数组中 67 NSMutableArray *array = [NSMutableArray array]; 68 for (NSDictionary *dict in dictArray) { 69 //创建模型对象 70 KZApp *appModel = [KZApp appWithApp:dict]; 71 //添加模型对象到数组中 72 [array addObject:appModel]; 73 } 74 75 _images = array; 76 77 78 } 79 return _images; 80 } 81 82 83 //发现代码中previous和next方法中的代码基本上一样,属于重复性的,可以将其封装成一个方法 84 - (void)move{ 85 86 //创建一个字典,接收当前索引下的数据 87 //NSDictionary *dict = self.images[self.index]; 88 89 KZApp *appModel = self.images[self.index]; 90 91 //设置noLabel的内容 92 self.noLabel.text = [NSString stringWithFormat:@"%d/%d",self.index+1,self.images.count]; 93 //设置图片 94 //self.iconView.image = [UIImage imageNamed:dict[icon]]; 95 self.iconView.image = [UIImage imageNamed:appModel.icon]; 96 //设置图片描述 97 //self.descLabel.text = dict[desc]; 98 self.descLabel.text = appModel.desc; 99 100 101 102 //设置按钮的不可用状态,当计数器为0时,左边的按钮为不可用状态 103 self.left.enabled = self.index != 0; 104 //当计数器为4时,右边的按钮为不可用状态 105 self.right.enabled = self.index != (self.images.count - 1); 106 } 107 - (IBAction)previous{ 108 109 //计数器减一 110 self.index--; 111 [self move]; 112 } 113 - (IBAction)next{ 114 self.index++; 115 [self move]; 116 } 117 @end
至此,图片浏览器小实例就改进到此,代码肯定还有不是很好的可以改进的地方,以后再做修改.