ios开发-UI基础-应用管理(单纯界面)改进2

王朝学院·作者佚名  2016-08-27
窄屏简体版  字體: 小  |  中  |  大  |  超大  

本篇文章,通过字典转模型来改进上篇文章中的代码.

字典转模型,之前的文章已经介绍过,这里再重复一下:

字典转模型

字典:用来存储数据的,用键值对存储数据,是一个nsdictionary ,(不好处:key值容易写错)

模型: 用来存储数据的,一个字典对应一个模型,模型用属性来存储数据,是一个纯洁的object对象

@PRoperty(nonatomic,copy)NSString *name;

@property(nonatomic,copy)NSString *icon;

字典转模型:一个字典对应一个模型,把键值对转化模型的属性,就是把键值对的value赋值给模型的属性

appModel.name = dict[@"name"];

appModel.icon = dict[@"icon"];

属性的类型和名称:属性的类型和键值对的key值的类型是一样,最好名称也和key值的名称一样

* 字典缺陷:

0> 写代码的时候字典的键没有智能提示, 但是模型的属性可以有智能提示

1> "键"是字符串, 如果写错了, 编译器不报错(在编译的时候不报错), 运行时可能出错, 出错了很难找错。

* 把字典转模型的过程封装到"模型"内部

* 原因: 将来的这个"模型"可能会在很多地方被用到(比如有很多个控制器都会使用这个模型), 那么每次用到模型的地方都需要写一次把字典中的数据赋给模型属性的代码, 此时如果把这些赋值语句封装到模型内部, 会大大简化了使用复杂度与代码量。

*实现思路:

1> 在模型中接收一个NSDictionary的参数, 然后在模型内部把NSDictioanry中的键值对数据赋值给模型的属性。

2> 封装一个initWithDict方法和一个appWithDict方法(规范)

- (instancetype)initWithDict:(NSDictionary *)dict{}

+(instancetype)appModelWithDict:(NSDictionary *)dict{}

应用代码结构及plist截图;

下面附上源代码:

KZAppModel.h

1//2//KZAppModel.h3//UI基础-03-05-144//5//Created by hukezhu on 15/5/15.6//7//89#import<Foundation/Foundation.h>1011@interfaceKZAppModel : NSObject12/**13* 应用图标14*/15@property (nonatomic ,copy) NSString *icon;16/**17* 应用名称18*/19@property (nonatomic ,copy) NSString *name;2021/**22* 通过字典来初始化对象23*24* @param dict 字典对象25*26* @return 已经初始化完毕的模型对象27*/28- (instancetype)initWithDict:(NSDictionary *)dict;2930//类方法31+ (instancetype)appWithModelDict:(NSDictionary *)dict;3233@end

KZAppModel.m

1//2//KZAppModel.m3//UI基础-03-05-144//5//Created by hukezhu on 15/5/15.6//7//89#import"KZAppModel.h"1011@implementationKZAppModel12//对象方法13-(instancetype)initWithDict:(NSDictionary *)dict{1415//重写构造方法的默认写法16if(self =[super init]){1718//将字典的所有属性赋值给模型19self.icon = dict[@"icon"];20self.name = dict[@"name"];21}22returnself;23}24//类方法25+(instancetype)appWithModelDict:(NSDictionary *)dict{2627//注意此处是self28return[[self alloc]initWithDict:dict];29}30@end

ViewController.m:

1//2//ViewController.m3//03-应用管理4//5//Created by hukezhu on 15/5/14.6//7//89#import"ViewController.h"10#import"KZAppModel.h"1112@interfaceViewController ()13@property (nonatomic,strong)NSArray *apps;14@end1516@implementationViewController1718- (void)viewDidLoad {19[super viewDidLoad];2021//每一行的应用的个数22inttotalCol =3;232425//添加一个小的view26CGFloat appW =80;27CGFloat appH =100;28CGFloat marginX =20;29CGFloat marginY =20;30CGFloat hightMargin =30;31CGFloat leftMargin = (self.view.frame.size.width - totalCol * appW - (totalCol -1) *marginX)*0.5;32333435for(inti =0; i < self.apps.count; i++) {363738//计算行号和列号39introw = i /totalCol;40intcol = i %totalCol;4142CGFloat appX = leftMargin + (marginX + appW)*col;43CGFloat appY = hightMargin + (marginY + appH)*row;4445//1.添加view4647//1.1新建一个UIView48UIView *appView =[[UIView alloc]init];49//1.2设置frame50appView.frame =CGRectMake(appX, appY, appW, appH);51//1.3设置背景色(便于代码阶段验证,之后会删除)52//appView.backgroundColor = [UIColor redColor];53//1.4将这个appView添加到view中54[self.view addSubview:appView];5556//加载数据57//NSDictionary *dict = self.apps[i];58//将数据赋值给模型对象59KZAppModel *appModel =self.apps[i];6061//2.添加图片UIImageView62CGFloat imageW =60;63CGFloat imageH =50;64CGFloat imageX = (appW - imageW)*0.5;65CGFloat imageY =0;66UIImageView *imageView =[[UIImageView alloc]init];67imageView.frame =CGRectMake(imageX, imageY, imageW, imageH);68//imageView.backgroundColor = [UIColor blueColor];69//imageView.image = [UIImage imageNamed:dict[@"icon"]];70//从模型对象中取出数据71imageView.image =[UIImage imageNamed:appModel.icon];72[appView addSubview:imageView];737475//3.添加应用名称7677CGFloat labelW =80;78CGFloat labelH =25;79CGFloat labelX =0;80CGFloat labelY =imageH;81UILabel *label =[[UILabel alloc]init];82label.frame =CGRectMake(labelX, labelY, labelW, labelH);83//label.backgroundColor = [UIColor grayColor];84//label.text = dict[@"name"];85//从模型对象中取出数据name86label.text =appModel.name;8788//设置字体大小89label.font = [UIFont systemFontOfSize:13];90//设置字体居中91label.textAlignment =NSTextAlignmentCenter;92[appView addSubview:label];9394//4.添加下载按钮9596CGFloat downloadW =60;97CGFloat downloadH =25;98CGFloat downloadX =10;99CGFloat downloadY = labelH +labelY;100UIButton *downloadBtn =[[UIButton alloc]init];101downloadBtn.frame =CGRectMake(downloadX, downloadY, downloadW, downloadH);102//downloadBtn.backgroundColor = [UIColor yellowColor];103//设置背景图片104[downloadBtn setBackgroundImage:[UIImage imageNamed:@"buttongreen"] forState:UIControlStateNormal];105[downloadBtn setBackgroundImage:[UIImage imageNamed:@"buttongreen_highlighted"] forState:UIControlStateHighlighted];106//设置字体第一种方法107[downloadBtn setTitle:@"下载"forState:UIControlStateNormal];108109//设置字体第二种方法(不推荐使用)110downloadBtn.titleLabel.text =@"下载";111112//设置字体大小113downloadBtn.titleLabel.font = [UIFont systemFontOfSize:15];114[appView addSubview:downloadBtn];115116117[downloadBtn addTarget:self action:@selector(btnOnClick:) forControlEvents:UIControlEventTouchUpInside];118}119120121122123124}125/**126* 按钮的点击方法127*128* @param btn 将按钮本身传入方法中,哪个按钮被点击就调用这个方法129*/130- (void)btnOnClick:(UIButton *)btn{131132//NSLog(@"------%@",btn);133btn.enabled =NO;134[btn setTitle:@"已下载"forState:UIControlStateNormal];135136CGFloat labelW =120;137CGFloat labelH =30;138CGFloat labelX = (self.view.frame.size.width - labelW)*0.5;139CGFloat labelY = (self.view.frame.size.height - labelH)*0.5;140UILabel *label =[[UILabel alloc]init];141label.frame =CGRectMake(labelX, labelY, labelW, labelH);142label.text =@"正在下载";143//设置字体颜色144label.textColor =[UIColor redColor];145//设置字体居中146label.textAlignment =NSTextAlignmentCenter;147//设置 背景色148label.backgroundColor =[UIColor blackColor];149150//设置圆角的半径151label.layer.cornerRadius =8;152//将多余的部分减掉153label.layer.masksToBounds =YES;154//设置透明度155label.alpha =0.0;156//将label添加到view中157[self.view addSubview:label];158//使用block动画,动画持续时间2秒159[UIView animateWithDuration:2.0animations:^{160label.alpha =0.5;161} completion:^(BOOL finished) {162if(finished) {163[UIView animateWithDuration:2.0delay:0.1options:UIViewAnimationOptionCurveLinear animations:^{164label.alpha =0.0;165} completion:^(BOOL finished) {166//上面将透明度设置为0,界面上已经不显示这个label,但是它仍然在内存中,所以为了节约内存,仍要将其从内存中删除167[label removeFromSuperview];168169}];170}171}];172173}174/**175* "懒加载",加载应用数据176*177*/178- (NSArray *)apps{179180//如果_apps为空,才加载数据181if(_apps ==nil) {182//获取plist的全路径183NSString *path = [[NSBundle mainBundle]pathForResource:@"app.plist"ofType:nil];184185//加载数组186NSArray *dictArray =[NSArray arrayWithContentsOfFile:path];187188//创建一个可变数组,来动态接收模型对象189NSMutableArray *array =[NSMutableArray array];190191//通过循环,将字典数组的字典取出,转成模型对象192for(NSDictionary *dictindictArray) {193KZAppModel *appModel =[KZAppModel appWithModelDict:dict];194[array addObject:appModel];195}196_apps =array;197}198return_apps;199}200201- (void)didReceiveMemoryWarning {202[super didReceiveMemoryWarning];203//Dispose of any resources that can be recreated.204}205206@end

相比较上篇文章的代码增加的知识点:1.字典转模型

文章开头,以及前面的文章介绍了好多次了,这里不再赘述.

2.在模型类中,声明和实现方法的时候,定义的返回值类型为instancetype,这个与id的区别:

1. 使用id作为方法返回值的问题:

在接收方法的返回值的时候可以使用任何类型来接收, 编译都不报错, 但是运行时可能出错。

2. instancetype需要注意的点

1> instancetype在类型表示上, 与id意思一样, 都表示任何对象类型

2> instancetype只能用作返回值类型, 不能向id一样声明变量、用作参数等

3> 使用instancetype, 编译器会检测instancetype的真实类型, 如果类型不匹配, 编译时就发出警告。(instancetype出现在哪个类型中就表示对应的类型)

这里我们还是使用了代码来创建的空间,苹果提供了xib,用来描述局部界面的文件(相对于storyboard的描述全局文件来说),使用Xib我们可以通过拖拽的方法来进行可视化开发,比较方便,下篇文章,将使用xib来改进这个代码.

 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
© 2005- 王朝網路 版權所有 導航