iOS开发基础-九宫格坐标(2)之模型
在iOS开发基础-九宫格(1)中,属性变量 apps 是从plist文件中加载数据的,在 viewDidLoad 方法中的第20行、26行中,直接通过字典的键名来获取相应的信息,使得 ViewController 直接与数据打交道,如果频繁这样使用,可能会不小心把键名写错,而程序却不会报错。因此,考虑把字典数据转换成一个模型,把数据封装到模型中去,让 ViewController 与模型交互,而不与数据直接打交道。
修改iOS开发基础-九宫格(1)中的代码:
一、字典转模型介绍

字典转模型的好处:
1)降低代码的耦合度;
2)将字典转模型部分代码集中在一处处理,降低代码出错概率;
3)程序中,直接对模型的属性进行操作,提供编码效率。
4)调用时,不必关心模型内部的任何细节。
二、代码实例
新建一个类命名为 WJQAppInfo 继承自 NSObject ,在 WJQAppInfo.h 头文件中声明公共的属性和方法:
//WJQAppInfo.h,模型类
#import <UIKit/UIKit.h> @interface WJQAppInfo : NSObject
@property (nonatomic, copy) NSString *name; //图片名称
@property (nonatomic, copy) NSString *desc; //图片信息描述
@property (nonatomic, strong, readonly) UIImage *image; - (instancetype)initWithDict:(NSDictionary *)dict;
+ (instancetype)appInfoWithDict:(NSDictionary *)dict; //工厂方法
@end
定义属性时,会自动生成 setter 和 getter 方法,以及一个带下划线的成员变量。如果是 readonly 属性,则只生成 getter 方法,也没哟成员变量。
instancetype 会让编译器检查实例化对象的准确类型,其只能用于返回类型,不能当做参数使用。
WJQAppInfo 类的实现文件代码如下:
//WJQAppInfo.m
#import "WJQAppInfo.h" @interface WJQAppInfo ()
{
UIImage *_imageABC;
}
@end @implementation WJQAppInfo - (instancetype)initWithDict:(NSDictionary *)dict {
self = [super init];
if (self) {
self.name = dict[@"name"];
self.desc = dict[@"desc"];
}
return self;
} + (instancetype)appInfoWithDict:(NSDictionary *)dict {
return [[self alloc] initWithDict:dict];
} - (UIImage *)image {
if (!_imageABC) {
_imageABC = [UIImage imageNamed:self.name];
}
return _imageABC;
} @end
在 ViewController.m 文件中导入 WJQAppInfo 头文件。
修改属性 apps 的 getter 方法,代码如下:
//字典转换成WJQAppInfo模型
- (NSArray *)apps {
if (!_apps) {
NSString *path = [[NSBundle mainBundle] pathForResource:@"Data" ofType:@"plist"];
//_apps = [NSArray arrayWithContentsOfFile:path];
NSArray *array = [NSArray arrayWithContentsOfFile:path];
NSMutableArray *arrayM = [NSMutableArray array];
for (NSDictionary *dict in array) {
//遍历数组,将数据在的字典依次转化为WJQAppInfo对象,并添加到临时对象arrayM中去
//用字典来实例化对象的工厂方法
[arrayM addObject:[WJQAppInfo appInfoWithDict:dict]];
}
_apps = arrayM;
}
return _apps;
}
修改 viewDidLoad 代码如下:
- (void)viewDidLoad {
[super viewDidLoad];
int totalColumn = ; //3列
CGFloat margin = (self.view.frame.size.width - totalColumn*appViewWidth) / (totalColumn + );
int count = self.apps.count;
NSLog(@"%d", count);
for (int i = ; i < count; i++) {
int row = i/totalColumn; //行号,从0开始
int column = i%totalColumn; //列号,从0开始
CGFloat appViewX = margin + (margin + appViewWidth) * column; //子视图的X坐标
CGFloat appViewY = margin + (margin + appViewHeight) * row; //子视图的Y坐标
//创建UIView控件
UIView *appView = [[UIView alloc] initWithFrame:CGRectMake(appViewX, appViewY, appViewWidth, appViewHeight)];
[self.view addSubview:appView];
//创建上述UIView控件的子视图,创建图像信息
UIImageView *appImageView = [[UIImageView alloc] initWithFrame:CGRectMake(, , , )];
WJQAppInfo *appInfo = self.apps[i];
UIImage *appImage = appInfo.image;
appImageView.image = appImage; //设置图片
[appImageView setContentMode:UIViewContentModeScaleAspectFit];
[appView addSubview:appImageView];
//创建上述UIView控件的子视图,创建UILabel信息描述标签
UILabel *appLabel = [[UILabel alloc] initWithFrame:CGRectMake(, , , )];
[appLabel setText:appInfo.desc]; //设置图片信息描述
[appLabel setTextAlignment:NSTextAlignmentCenter];
[appLabel setFont:[UIFont systemFontOfSize:12.0]];
[appLabel setTextColor:[UIColor blueColor]];
[appView addSubview:appLabel];
//创建下载按钮
UIButton *appButton = [UIButton buttonWithType:UIButtonTypeCustom];
appButton.frame = CGRectMake(, , , );
[appButton setBackgroundImage:[UIImage imageNamed:@"download"] forState:UIControlStateNormal];
[appButton setBackgroundImage:[UIImage imageNamed:@"downloaded"] forState:UIControlStateHighlighted];
[appButton setTitle:@"下载" forState:UIControlStateNormal];
appButton.titleLabel.font = [UIFont systemFontOfSize:12.0];
[appButton setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
[appView addSubview:appButton];
[appButton addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
}
}
使用 KVC 重新写模型类中的 initWithDict: 方法:
//WJQAppInfo.m
- (instancetype)initWithDict:(NSDictionary *)dict {
self = [super init];
if (self) {
[self setValue:dict[@"name"] forKey:@"name"];
[self setValue:dict[@"desc"] forKey:@"desc"];
}
return self;
}
或者使用 setValuesForKeysWithDictionary: 方法再对该方法进行修改:
//WJQAppInfo.m
- (instancetype)initWithDict:(NSDictionary *)dict {
self = [super init];
if (self) {
[self setValuesForKeysWithDictionary:dict];
}
return self;
}
setValuesForKeysWithDictionary: 方法会遍历形参 dict 中每个键值调用 setValue:forKey: 方法,但是当字典中有某个键值而调用的对象没有相应的属性时,系统会崩溃。
参考博客:iOS开发UI篇—字典转模型
实例代码:http://pan.baidu.com/s/1i4aQTFZ
iOS开发基础-九宫格坐标(2)之模型的更多相关文章
- iOS开发基础-九宫格坐标(6)
继续对iOS开发基础-九宫格坐标(5)中的代码进行优化. 优化思路:把字典转模型部分的数据处理操作也拿到模型类中去实现,即将 ViewController 类实现中 apps 方法搬到 WJQAppI ...
- iOS开发基础-九宫格坐标(5)
继续在iOS开发基础-九宫格坐标(4)的基础上进行优化. 一.改进思路 1)iOS开发基础-九宫格坐标(4)中 viewDidLoad 方法中的第21.22行对控件属性的设置能否拿到视图类 WJQAp ...
- iOS开发基础-九宫格坐标(4)
对iOS开发基础-九宫格坐标(3)的代码进行进一步优化. 新建一个 UIView 的子类,并命名为 WJQAppView ,将 appxib.xib 中的 UIView 对象与新建的视图类进行关联. ...
- iOS开发基础-九宫格坐标(3)之Xib
延续iOS开发基础-九宫格坐标(2)的内容,对其进行部分修改. 本部分采用 Xib 文件来创建用于显示图片的 UIView 对象. 一.简单介绍 Xib 和 storyboard 的比较: 1) X ...
- iOS开发基础-九宫格坐标(1)
一.功能分析 1)以九宫格展示图片信息,每一个 UIView 包含一个 UIImageView .一个 UILabel 和一个 UIButton . 2)加载App数据,根据数据长度创建对应的格子数: ...
- IOS开发基础知识碎片-导航
1:IOS开发基础知识--碎片1 a:NSString与NSInteger的互换 b:Objective-c中集合里面不能存放基础类型,比如int string float等,只能把它们转化成对象才可 ...
- iOS开发——总结篇&IOS开发基础知识
IOS开发基础知识 1:Objective-C语法之动态类型(isKindOfClass, isMemberOfClass,id) 对象在运行时获取其类型的能力称为内省.内省可以有多种方法实现. 判断 ...
- IOS开发基础环境搭建
一.目的 本文的目的是windows下IOS开发基础环境搭建做了对应的介绍,大家可根据文档步骤进行mac环境部署: 二.安装虚拟机 下载虚拟机安装文件绿色版,点击如下文件安装 获取安装包: ...
- iOS开发基础-图片切换(4)之懒加载
延续:iOS开发基础-图片切换(3),对(3)里面的代码用懒加载进行改善. 一.懒加载基本内容 懒加载(延迟加载):即在需要的时候才加载,修改属性的 getter 方法. 注意:懒加载时一定要先判断该 ...
随机推荐
- bisect模块(使用二分法将数据按顺序插入一个列表)
bisect模块功能:使用二分法将数据按顺序插入一个列表 该模块主要有两个函数: 1.insort_right ====>按从小到大顺序将数据插入一个列表 2.bisect_right ...
- ZXing 生成、读取二维码(带logo)
前言 ZXing,一个支持在图像中解码和生成条形码(如二维码.PDF 417.EAN.UPC.Aztec.Data Matrix.Codabar)的库.ZXing(“zebra crossing”)是 ...
- C++系列总结——mutable关键字
介绍 mutable的中文意思是易变的,是C++的一个关键字.它的作用就是允许修改被const修饰的对象的成员变量. 常用场景 什么情况下我们会使用到mutable? 一般我们会用const修饰get ...
- Python re 模块
Python re 模块 TOC 介绍 作用 正则表达式语法 贪婪和非贪婪 普通字符和特殊字符 分组(比较重要) re modul level 方法 正则表达式对象 匹配对象 常用例子 注意事项 Ja ...
- 详解原生JS回到顶部
第一次知道可以用超链接(锚点)实现回到顶部的时候我是很震惊的,想着原来可以这么简单啊!但是作为一个正在学习JS的小白,不能就这么轻易止步,所以查资料自己整了一个JS返回顶部. HTML代码: ? 1 ...
- elasticsearch常用命令
elasticsearch的rest访问格式: curl -X<REST Verb> <Node>:<Port>/<Index>/<Type> ...
- SQLServer之修改表值函数
修改表值函数注意事项 更改先前通过执行 CREATE FUNCTION 语句创建的现有 Transact-SQL 或 CLR 函数,但不更改权限,也不影响任何相关的函数.存储过程或触发器. 不能用 A ...
- man -f/-k [keyword]在fedora 29 中报错nothing appropriate
我们在使用 man 手册的时候,可以使用man -f [keyword]去查询keyword的在线文档,但是这时候会报错:(图来源自网络) 这是因为我们还没有建立 man 手册的索引缓存: 我们可以使 ...
- 5.6Python数据处理篇之Sympy系列(六)---矩阵的操作
目录 目录 前言 (一)矩阵的创建-Matrix() 1.说明: 2.源代码: 3.输出: (二)常用的构造矩阵 1.说明: 2.源代码: 3.输出: (三)基本操作 1.说明: 2.源代码: 3.输 ...
- docker-compose编排项目redis容器实现主从复制
一.pip管理工具安装 docker-compose是python项目,所以安装需要通过python下的包管理工具pip安装.一般linux服务器都会预安装有python环境,所以优先检查python ...