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 方法. 注意:懒加载时一定要先判断该 ...
随机推荐
- Select默认选择后台参数
之前写过一个这样的方法,后来需求开发中,发现了方法的BUG,然后我又重新找了一种方法,今天来记录一下. 先声明前台 <select name="type" class=&qu ...
- Python并发编程之消息队列补充及如何创建线程池(六)
大家好,并发编程 进入第六篇. 在第四章,讲消息通信时,我们学到了Queue消息队列的一些基本使用.昨天我在准备如何创建线程池这一章节的时候,发现对Queue消息队列的讲解有一些遗漏的知识点,而这些知 ...
- 一统江湖的大前端(3) DOClever——你的postman有点low
<一统江湖的大前端>系列是自己的前端学习笔记,旨在介绍javascript在非网页开发领域的应用案例和发现各类好玩的js库,不定期更新.如果你对前端的理解还是写写页面绑绑事件,那你真的是有 ...
- EBGP在非直连网络时,需要配置ebgp的最大跳数,否则无法建立非直连的EBGP邻居
结论: 1.默认情况下,EBGP只能在物理直连的路由器之间建立邻居. 2.要想配置非直连设备间的BGP邻居,必须加配置. 组网图: 抓包: 1.默认情况下,EBGP邻居之间的BGP报文的TTL为1. ...
- Django Linux环境下部署CentOS7+Python3+Django+uWSGI+Nginx(含Nginx返回400问题处理、防火墙管理)
本文将介绍如何在Linux系统上部署Django web项目,本次部署基于下面的架构: CentOS7+ Python3.5 + Django1.11 + uWSGI + Nginx 亲测可行!!按照 ...
- git清空版本记录
在网上找的,记录下来自己使用 1.新增分支 git checkout --orphan latest_branch 2. 添加问题 git add -A 3. 提交 git commit -am &q ...
- 在本地硬盘安装WinPE系统,实现UEFI引导,摆脱U盘
之前装系统一直用U盘装PE后再装系统,这次直接想把PE系统直接装在本地某个分区中,普通的PE制作工具只能直接装在一个硬盘里没法装在某个分区,百度发现没有一篇类似的文章,只能自己想办法了.目前的PE都支 ...
- Leaflet实现动态线路
一.引用Leaflet脚本样式,和Leaflet Ant Path 插件 下载地址: Leaflet:https://leafletjs.com/download.html Leaflet Ant P ...
- Swift JSON字符串和字典以及数组的互转
1.JSONString转换为字典 // JSONString转换为字典 func getDictionaryFromJSONString(jsonString:String) ->NSDict ...
- Python爬虫之正则表达式(2)
# 最常规的匹配 import re content = 'Hello 123 4567 World_This is a Regex Demo' print(len(content)) result ...