一:字典转模型好处
1、使用字典的坏处
手敲字符串key,key容易写错
Key如果写错了,编译器不会有任何警告和报错,造成设错数据或者取错数据
不面向对象
2、使用对象的好处
面向对象,对象把显示世界中的内容抽象到程序的世界,更直观,更接近人类的语言
所谓模型,其实就是数据模型,专门用来存放数据的对象,用它来表示数据会更加专业
模型设置数据和取出数据都是通过它的属性,属性名如果写错了,编译器会马上报错,因此,保证了数据的正确性
使用模型访问属性时,编译器会提供一系列的提示,提高编码效率
二:1.readonly属性
(1)@property中readonly表示不允许修改对象的指针地址,但是可以修改对象的属性。
(2)通常使用@property关键字定义属性时,会生成getter&setter方法,还会生成一个带下划线的成员变量。
(3)如果是readonly属性,只会生成getter方法,不会生成带下划线的成员变量.
2.instancetype类型
(1)instancetype会让编译器检查实例化对象的准确类型
(2)instancetype只能用于返回类型,不能当做参数使用
3.instancetype & id的比较
(1) instancetype在类型表示上,跟id一样,可以表示任何对象类型
(2) instancetype只能用在返回值类型上,不能像id一样用在参数类型上
(3) instancetype比id多一个好处:编译器会检测instancetype的真实类型
三:数据模型封装步骤:
1,创建一个模型对象,对象内的成员属性跟字典中的键一一对应起来 2,模型对象提供两个方法 2.1 一个类方法: 2.2 一个构造方法:初始化成员变量的值(利用字典中的键值对) 3, 提供一个类方法,给外界提供一个接口, 3.1 类方法中完成plist文件的加载转成字典 3.2 类方法内完成字典转模型的封装过程
四:代码
模型数据声明文件
#import <Foundation/Foundation.h> // 封装数据模型 @interface LLAppInfo : NSObject /** 图片 */ @property (nonatomic, copy) NSString *icon; /** 名称 */ @property (nonatomic, copy) NSString *name; #warning instancetype 和 id的区别 + (instancetype)appInfoWithDic:(NSDictionary *)dic; - (instancetype)initWithDic:(NSDictionary *)dic; + (NSArray *)array; @end
模型数据实现文件
#import "LLAppInfo.h" @implementation LLAppInfo - (instancetype)initWithDic:(NSDictionary *)dic { if (self = [super init]) { self.name = dic[@"name"]; self.icon = dic[@"icon"]; } return self; } + (instancetype)appInfoWithDic:(NSDictionary *)dic { return [[self alloc] initWithDic:dic]; } + (NSArray *)array { NSString *path = [[NSBundle mainBundle] pathForResource:@"app.plist" ofType:nil]; NSArray *dicArray = [NSArray arrayWithContentsOfFile:path]; NSMutableArray *appInfoM = [[NSMutableArray alloc] initWithCapacity:dicArray.count]; for (NSDictionary *dic in dicArray) { [appInfoM addObject:[self appInfoWithDic:dic]]; } return appInfoM; } @end
控制器中的代码
#warning 数据模型封装的步骤:字典转模型 /** 1,创建一个模型对象,对象内的成员属性跟字典中的键一一对应起来 2,模型对象提供两个方法 2.1 一个类方法: 2.2 一个构造方法:初始化成员变量的值(利用字典中的键值对) 3, 提供一个类方法,给外界提供一个接口, 3.1 类方法中完成plist文件的加载转成字典 3.2 类方法内完成字典转模型的封装过程 */ #import "ViewController.h" #import "LLAppInfo.h" @interface ViewController () // 1,创建接受模型数据的数组 @property (nonatomic, strong) NSArray *appInfos; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. // 创建九宫格 [self createView]; } #pragma mark - 创建九宫格 - (void)createView { // 1, // 1,1 列数 int colnumCount = 3; CGFloat subViewWH= 100; CGFloat marginX = (self.view.frame.size.width - 3*subViewWH) / (colnumCount + 1); for (int i = 0; i<self.appInfos.count; i++) { // 计算行、列 int row = i/colnumCount; int col = i%colnumCount; // 创建subView UIView *subView = [[UIView alloc] init]; // subView.backgroundColor = [UIColor redColor]; [self.view addSubview:subView]; // 确定subView的frame CGFloat subViewX = marginX + (marginX + subViewWH) * col; CGFloat subViewY = 30 + (marginX + subViewWH) * row; subView.frame = CGRectMake(subViewX, subViewY, subViewWH, subViewWH); #warning 将子控件添加到一个定义的view中的好处 // 数据 // NSDictionary *appInfo = self.appInfos[i]; LLAppInfo *appInfo = self.appInfos[i]; // 创建子控件 [self creatSubView:subView appInfo:appInfo]; } } #pragma mark - 创建子控件 - (void)creatSubView:(UIView *)subView appInfo:(LLAppInfo *)appInfo { // 1,创建图片 UIImageView *iconView = [[UIImageView alloc] init]; [subView addSubview:iconView]; // 1,1计算frame CGFloat iconViewWH = 60; CGFloat iconViewX = (subView.frame.size.width - iconViewWH) * 0.5; CGFloat iconViewY = 0; iconView.frame = CGRectMake(iconViewX, iconViewY, iconViewWH, iconViewWH); // 1,2添加数据 // iconView.image = [UIImage imageNamed:appInfo[@"icon"]]; // 这就是封装的好处,控制器管理的东西太多 iconView.image = [UIImage imageNamed:appInfo.icon]; // 2,创建名称 UILabel *titleView = [[UILabel alloc] init]; [subView addSubview:titleView]; titleView.textAlignment = NSTextAlignmentCenter; // titleView.numberOfLines = 0; titleView.font = [UIFont systemFontOfSize:13]; CGFloat titleViewX = 0; CGFloat titleViewY = CGRectGetMaxY(iconView.frame); CGFloat titleViewW = subView.frame.size.width; CGFloat titleViewH = 20; titleView.frame = CGRectMake(titleViewX, titleViewY, titleViewW, titleViewH); // titleView.text = appInfo[@"name"]; titleView.text = appInfo.name; // 3,创建按钮 UIButton *downView = [UIButton buttonWithType:UIButtonTypeCustom]; [subView addSubview:downView]; [downView setTitle:@"下载" forState:UIControlStateNormal]; [downView setBackgroundImage:[UIImage imageNamed:@"buttongreen"] forState:UIControlStateNormal]; [downView setBackgroundImage:[UIImage imageNamed:@"buttongreen_highlighted" ] forState: UIControlStateHighlighted]; #warning 设置按钮字体 // 设置按钮字体 downView.titleLabel.font = [UIFont systemFontOfSize:13]; CGFloat downViewX = iconViewX; CGFloat downViewY = CGRectGetMaxY(titleView.frame); CGFloat downViewW = iconViewWH; CGFloat downViewH = 20; downView.frame = CGRectMake(downViewX, downViewY, downViewW, downViewH); } #pragma mark - 懒加载模型数据 - (NSArray *)appInfos { if (!_appInfos) { #warning NSBundle // NSLog(@"%@", NSHomeDirectory()); // 1,重plist中读取数据 // NSString *path = [[NSBundle mainBundle] pathForResource:@"app.plist" ofType:nil]; // NSArray *appInfo = [NSArray arrayWithContentsOfFile:path]; // // // _appInfos = appInfo; // NSLog(@"%@", _appInfos); // 直接从封装好的代码中取数据 _appInfos = [LLAppInfo array]; } return _appInfos; } @end