在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)之模型的更多相关文章

  1. iOS开发基础-九宫格坐标(6)

    继续对iOS开发基础-九宫格坐标(5)中的代码进行优化. 优化思路:把字典转模型部分的数据处理操作也拿到模型类中去实现,即将 ViewController 类实现中 apps 方法搬到 WJQAppI ...

  2. iOS开发基础-九宫格坐标(5)

    继续在iOS开发基础-九宫格坐标(4)的基础上进行优化. 一.改进思路 1)iOS开发基础-九宫格坐标(4)中 viewDidLoad 方法中的第21.22行对控件属性的设置能否拿到视图类 WJQAp ...

  3. iOS开发基础-九宫格坐标(4)

    对iOS开发基础-九宫格坐标(3)的代码进行进一步优化. 新建一个 UIView 的子类,并命名为 WJQAppView ,将 appxib.xib 中的 UIView 对象与新建的视图类进行关联. ...

  4. iOS开发基础-九宫格坐标(3)之Xib

    延续iOS开发基础-九宫格坐标(2)的内容,对其进行部分修改. 本部分采用 Xib 文件来创建用于显示图片的 UIView 对象. 一.简单介绍  Xib 和 storyboard 的比较: 1) X ...

  5. iOS开发基础-九宫格坐标(1)

    一.功能分析 1)以九宫格展示图片信息,每一个 UIView 包含一个 UIImageView .一个 UILabel 和一个 UIButton . 2)加载App数据,根据数据长度创建对应的格子数: ...

  6. IOS开发基础知识碎片-导航

    1:IOS开发基础知识--碎片1 a:NSString与NSInteger的互换 b:Objective-c中集合里面不能存放基础类型,比如int string float等,只能把它们转化成对象才可 ...

  7. iOS开发——总结篇&IOS开发基础知识

    IOS开发基础知识 1:Objective-C语法之动态类型(isKindOfClass, isMemberOfClass,id) 对象在运行时获取其类型的能力称为内省.内省可以有多种方法实现. 判断 ...

  8. IOS开发基础环境搭建

    一.目的 本文的目的是windows下IOS开发基础环境搭建做了对应的介绍,大家可根据文档步骤进行mac环境部署: 二.安装虚拟机 下载虚拟机安装文件绿色版,点击如下文件安装 获取安装包:       ...

  9. iOS开发基础-图片切换(4)之懒加载

    延续:iOS开发基础-图片切换(3),对(3)里面的代码用懒加载进行改善. 一.懒加载基本内容 懒加载(延迟加载):即在需要的时候才加载,修改属性的 getter 方法. 注意:懒加载时一定要先判断该 ...

随机推荐

  1. 打造自己的.NET Core项目模板

    前言 每个人都有自己习惯的项目结构,有人的喜欢在项目里面建解决方案文件夹:有的人喜欢传统的三层命名:有的人喜欢单一,简单的项目一个csproj就搞定.. 反正就是萝卜青菜,各有所爱. 可能不同的公司对 ...

  2. 谈谈.NET Core中基于Generic Host来实现后台任务

    目录 前言 什么是Generic Host 后台任务示例 控制台形式 消费MQ消息的后台任务 Web形式 部署 IHostedService和BackgroundService的区别 IHostBui ...

  3. 使用开源项目Alipay.AopSdk.Core完成支付宝网页登录

    核心方法: public IActionResult UserInfoCallBackAli() { var alipayClient = new DefaultAopClient(ConfigAli ...

  4. [T-SQL] NCL INDEX 欄位選擇效能影響-解析

    因為這篇文章寫的比較長一些,我就將總結先列出來 總結 1. 除了WHERE條件外,JOINColumn除了記得建立索引,也要注意到選擇性的高低,如果真的找不到可用的Column,可以考慮在兩邊關聯的表 ...

  5. 聊聊我的 Java 自学之路

    最近经常在知乎收到类似『没基础,java 如何自学』.『怎么才能掌握编程』等等问题,再加上发现高中同学也在自学.有感而发,讲讲我的自学之路. 1.1. 大学 高考没正常发挥,考入一所二流的学校,当时分 ...

  6. arcgis api 3.x for js 入门开发系列十叠加 SHP 图层(附源码下载)

    前言 关于本篇功能实现用到的 api 涉及类看不懂的,请参照 esri 官网的 arcgis api 3.x for js:esri 官网 api,里面详细的介绍 arcgis api 3.x 各个类 ...

  7. Windows7 WIN 7 64位 环境编译6sv2.1版本的大气传输模型

    从来没见过Fortran...这次为了添加国产卫星光谱响应的支持,只能从零开始肯了. 6S模型主页:http://6s.ltdri.org/index.html. 下载最新的2015年更新的6SV2. ...

  8. office2019下载以及激活密钥(亲测可用)

    office2019激活密钥 W8W6K-3N7KK-PXB9H-8TD8W-BWTH9  或者: 链接:https://pan.baidu.com/s/1Ch0rc2ZN9I_lwmbjGESTuw ...

  9. C# Math的说有函数 以及说明

    Math.Abs(x)                                      x绝对值 Math.Acos(x)                                  ...

  10. 爬虫基础--IO多路复用单线程异步非阻塞

    最近一直的学习爬虫  ,进行基础的学习 性能相关 参考 https://www.cnblogs.com/wupeiqi/p/6229292.html # 目标:单线程实现并发HTTP请求 # # so ...