·您现在的位置: 云翼网络 >> 文章中心 >> 网站建设 >> app软件开发 >> IOS开发 >> ios开发-UI基础-应用管理(单纯界面)改进2

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

作者:佚名      IOS开发编辑:admin      更新时间:2022-07-23

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

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

   字典转模型
    字典:用来存储数据的,用键值对存储数据,是一个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.h
 3 //  UI基础-03-05-14
 4 //
 5 //  Created by hukezhu on 15/5/15.
 6 //
 7 //
 8 
 9 #import <Foundation/Foundation.h>
10 
11 @interface KZAppModel : NSObject
12 /**
13  *  应用图标
14  */
15 @property (nonatomic ,copy) NSString *icon;
16 /**
17  *  应用名称
18  */
19 @property (nonatomic ,copy) NSString *name;
20 
21 /**
22  *  通过字典来初始化对象
23  *
24  *  @param dict 字典对象
25  *
26  *  @return 已经初始化完毕的模型对象
27  */
28 - (instancetype)initWithDict:(NSDictionary *)dict;
29 
30 //类方法
31 + (instancetype)appWithModelDict:(NSDictionary *)dict;
32 
33 @end

 

 

  KZAppModel.m

 1 //
 2 //  KZAppModel.m
 3 //  UI基础-03-05-14
 4 //
 5 //  Created by hukezhu on 15/5/15.
 6 //
 7 //
 8 
 9 #import "KZAppModel.h"
10 
11 @implementation KZAppModel
12 //对象方法
13 -(instancetype)initWithDict:(NSDictionary *)dict{
14 
15     //重写构造方法的默认写法
16     if(self = [super init]){
17     
18         //将字典的所有属性赋值给模型
19         self.icon = dict[@"icon"];
20         self.name = dict[@"name"];
21     }
22     return self;
23 }
24 //类方法
25 +(instancetype)appWithModelDict:(NSDictionary *)dict{
26 
27     //注意此处是self
28     return [[self alloc]initWithDict:dict];
29 }
30 @end

 

 

  ViewController.m:

  1 //
  2 //  ViewController.m
  3 //  03-应用管理
  4 //
  5 //  Created by hukezhu on 15/5/14.
  6 //
  7 //
  8 
  9 #import "ViewController.h"
 10 #import "KZAppModel.h"
 11 
 12 @interface ViewController ()
 13 @property (nonatomic,strong)NSArray *apps;
 14 @end
 15 
 16 @implementation ViewController
 17 
 18 - (void)viewDidLoad {
 19     [super viewDidLoad];
 20     
 21     //每一行的应用的个数
 22     int totalCol = 3;
 23     
 24     
 25     //添加一个小的view
 26     CGFloat appW = 80;
 27     CGFloat appH = 100;
 28     CGFloat marginX = 20;
 29     CGFloat marginY = 20;
 30     CGFloat hightMargin = 30;
 31     CGFloat leftMargin = (self.view.frame.size.width - totalCol * appW - (totalCol - 1) *marginX)* 0.5;
 32     
 33     
 34     
 35     for (int i = 0; i < self.apps.count; i++) {
 36         
 37         
 38         //计算行号和列号
 39         int row = i / totalCol;
 40         int col = i % totalCol;
 41         
 42         CGFloat appX = leftMargin + (marginX + appW)* col;
 43         CGFloat appY = hightMargin + (marginY + appH)* row;
 44         
 45         //1.添加view
 46         
 47         //1.1新建一个UIView
 48         UIView *appView = [[UIView alloc]init];
 49         //1.2设置frame
 50         appView.frame = CGRectMake(appX, appY, appW, appH);
 51         //1.3设置背景色(便于代码阶段验证,之后会删除)
 52         //appView.backgroundColor = [UIColor redColor];
 53         //1.4将这个appView添加到view中
 54         [self.view addSubview:appView];
 55         
 56         //加载数据
 57         //NSDictionary *dict = self.apps[i];
 58         //将数据赋值给模型对象
 59         KZAppModel *appModel = self.apps[i];
 60         
 61         //2.添加图片UIImageView
 62         CGFloat imageW = 60;
 63         CGFloat imageH = 50;
 64         CGFloat imageX = (appW - imageW)*0.5;
 65         CGFloat imageY = 0;
 66         UIImageView *imageView = [[UIImageView alloc]init];
 67         imageView.frame = CGRectMake(imageX, imageY, imageW, imageH);
 68         //imageView.backgroundColor = [UIColor blueColor];
 69         //imageView.image = [UIImage imageNamed:dict[@"icon"]];
 70         //从模型对象中取出数据
 71         imageView.image = [UIImage imageNamed:appModel.icon];
 72         [appView addSubview:imageView];
 73     
 74         
 75         //3.添加应用名称
 76     
 77         CGFloat labelW = 80;
 78         CGFloat labelH = 25;
 79         CGFloat labelX = 0;
 80         CGFloat labelY = imageH;
 81         UILabel *label = [[UILabel alloc]init];
 82         label.frame = CGRectMake(labelX, labelY, labelW, labelH);
 83         //label.backgroundColor = [UIColor grayColor];
 84         //label.text = dict[@"name"];
 85         //从模型对象中取出数据name
 86         label.text = appModel.name;
 87         
 88         //设置字体大小
 89         label.font = [UIFont systemFontOfSize:13];
 90         //设置字体居中
 91         label.textAlignment = NSTextAlignmentCenter;
 92         [appView addSubview:label];
 93         
 94         //4.添加下载按钮
 95         
 96         CGFloat downloadW = 60;
 97         CGFloat downloadH = 25;
 98         CGFloat downloadX = 10;
 99         CGFloat downloadY = labelH + labelY;
100         UIButton *downloadBtn = [[UIButton alloc]init];
101         downloadBtn.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];
108         
109         //设置字体第二种方法(不推荐使用)
110         downloadBtn.titleLabel.text = @"下载";
111         
112         //设置字体大小
113         downloadBtn.titleLabel.font = [UIFont systemFontOfSize:15];
114         [appView addSubview:downloadBtn];
115         
116         
117         [downloadBtn addTarget:self action:@selector(btnOnClick:) forControlEvents:UIControlEventTouchUpInside];
118     }
119     
120  
121     
122     
123     
124 }
125 /**
126  *  按钮的点击方法
127  *
128  *  @param btn 将按钮本身传入方法中,哪个按钮被点击就调用这个方法
129  */
130 - (void)btnOnClick:(UIButton *)btn{
131 
132     //NSLog(@"------%@",btn);
133     btn.enabled = NO;
134     [btn setTitle:@"已下载" forState:UIControlStateNormal];
135     
136     CGFloat labelW = 120;
137     CGFloat labelH = 30;
138     CGFloat labelX = (self.view.frame.size.width - labelW)* 0.5;
139     CGFloat labelY = (self.view.frame.size.height - labelH)*0.5;
140     UILabel *label = [[UILabel alloc]init];
141     label.frame = CGRectMake(labelX, labelY, labelW, labelH);
142     label.text = @"正在下载";
143     //设置字体颜色
144     label.textColor = [UIColor redColor];
145     //设置字体居中
146     label.textAlignment = NSTextAlignmentCenter;
147     //设置 背景色
148     label.backgroundColor = [UIColor blackColor];
149     
150     //设置圆角的半径
151     label.layer.cornerRadius = 8;
152     //将多余的部分减掉
153     label.layer.masksToBounds = YES;
154     //设置透明度
155     label.alpha = 0.0;
156     //将label添加到view中
157     [self.view addSubview:label];
158     //使用block动画,动画持续时间2秒
159     [UIView animateWithDuration:2.0 animations:^{
160         label.alpha = 0.5;
161     } completion:^(BOOL finished) {
162         if (finished) {
163             [UIView animateWithDuration:2.0 delay:0.1 options:UIViewAnimationOptionCurveLinear animations:^{
164                 label.alpha = 0.0;
165             } completion:^(BOOL finished) {
166                 //上面将透明度设置为0,界面上已经不显示这个label,但是它仍然在内存中,所以为了节约内存,仍要将其从内存中删除
167                 [label removeFromSuperview];
168                 
169             }];
170         }
171     }];
172     
173 }
174 /**
175  *  "懒加载",加载应用数据
176  *
177  */
178 - (NSArray *)apps{
179 
180     //如果_apps为空,才加载数据
181     if (_apps == nil) {
182         //获取plist的全路径
183         NSString *path = [[NSBundle mainBundle]pathForResource:@"app.plist" ofType:nil];
184 
185         //加载数组
186         NSArray *dictArray = [NSArray arrayWithContentsOfFile:path];
187         
188         //创建一个可变数组,来动态接收模型对象
189         NSMutableArray *array = [NSMutableArray array];
190         
191         //通过循环,将字典数组的字典取出,转成模型对象
192         for (NSDictionary *dict in dictArray) {
193             KZAppModel *appModel = [KZAppModel appWithModelDict:dict];
194             [array addObject:appModel];
195         }
196         _apps = array;
197     }
198     return _apps;
199 }
200 
201 - (void)didReceiveMemoryWarning {
202     [super didReceiveMemoryWarning];
203     // Dispose of any resources that can be recreated.
204 }
205 
206 @end

 

相比较上篇文章的代码增加的知识点:

  1.字典转模型

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

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

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

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

    2. instancetype需要注意的点
      1> instancetype在类型表示上, 与id意思一样, 都表示任何对象类型
      2> instancetype只能用作返回值类型, 不能向id一样声明变量、用作参数等
      3> 使用instancetype, 编译器会检测instancetype的真实类型, 如果类型不匹配, 编译时就发出警告。(instancetype出现在哪个类型中就表示对应的类型)  

 

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