iOS开发UI篇—从代码的逐步优化看MVC

iOS开发UI篇—从代码的逐步优化看MVC

一、要求

要求完成下面一个小的应用程序。

二、一步步对代码进行优化

注意:在开发过程中,优化的过程是一步一步进行的。(如果一个人要吃五个包子才能吃饱,那么他是否直接吃第五个,前面四个不用吃就饱了?)

1.完成基本要求的代码(使用了字典转模型和xib连线)

(1)文件结构

(2)主要代码

  字典转模型部分:

 TXApp.h头文件

 1 //  屌丝逆天-应用管理01
 2 //
 3 //  Created by 鑫 on 14-10-4.
 4 //  Copyright (c) 2014年 梁镋鑫. All rights reserved.
 5 //
 6 
 7 #import <Foundation/Foundation.h>
 8 
 9 @interface TXApp : NSObject
10 /**
11  * 图标的名称
12  */
13 @property(nonatomic,copy)NSString *name;
14 /**
15  *  图标
16  */
17 @property(nonatomic,copy)NSString *icon;
18 /**
19  *  通过字典初始化模型对象
20  *
21  *  @param dict 字典对象
22  *
23  *  @return 一初始化完毕的模型对象
24  */
25 -(instancetype)initWithDict:(NSDictionary *)dict;
26 +(instancetype)appWithDict:(NSDictionary *) dict;
27 @end

TXApp.m文件

 1 //  TXApp.m
 2 //  屌丝逆天-应用管理01
 3 //
 4 //  Created by 鑫 on 14-10-4.
 5 //  Copyright (c) 2014年 梁镋鑫. All rights reserved.
 6 //
 7 
 8 #import "TXApp.h"
 9 
10 @implementation TXApp
11 -(instancetype)initWithDict:(NSDictionary *)dict
12 {
13     if (self = [super init]) {
14         self.name = dict[@"name"];
15         self.icon = dict[@"icon"];
16     }
17     return self;
18 }
19 +(instancetype)appWithDict:(NSDictionary *)dict
20 {
21     return [[self alloc]initWithDict:dict];
22 }
23 @end

 xib部分(TXAppView.h文件):

注:(xib视图和TXAppView.m进行了关联,三个属性均进行了连线)  

 1 #import <UIKit/UIKit.h>
 2 @class TXApp;
 3 @interface TXAppView : UIView
 4 @property (weak, nonatomic) IBOutlet UIImageView *iconView;
 5 @property (weak, nonatomic) IBOutlet UILabel *namelable;
 6 /**
 7  *  模型
 8  */
 9 @property(nonatomic ,strong)TXApp *app;
10 /**
11  *  通过模型数据来创建一个view
12  */
13 +(instancetype)appViewWithApp:(TXApp *)app;
14 @end

主要功能实现部分:

TXViewController.m文

 1 #import "TXViewController.h"
 2 #import "TXApp.h"
 3 #import "TXAppView.h"
 4 @interface TXViewController ()
 5 /**
 6  *  传放应用信息
 7  */
 8 @property(nonatomic ,strong)NSArray *apps;
 9 
10 
11 @end
12 
13 @implementation TXViewController
14 
15 - (void)viewDidLoad
16 {
17     [super viewDidLoad];
18     
19     //添加应用信息
20     
21     //总列数(一行最多3列)
22     int totalColumns = 3;
23     
24     //应用尺寸
25     CGFloat appW = 85;
26     CGFloat appH = 90;
27     
28     //间隙 = (控制器view的宽度-3* 应用宽度)/4
29     CGFloat marginX = (self.view.frame.size.width - totalColumns * appW) / (totalColumns + 1);
30     CGFloat marginY = 15;
31     
32     //根据应用个数创建对用框框
33     
34     for (int index = 0; index < self.apps.count; index++) {
35         //3.1.创建view
36         NSBundle *bundle = [NSBundle mainBundle];
37         //读取xib文件(会创建xib中的描述的所有对象,并且安顺序放到数组中返回;
38         NSArray * objs = [bundle  loadNibNamed:@"TXAppView" owner:nil options:nil];
39         TXAppView *appView = [objs lastObject];
40         
41         //3.2添加view
42         [self.view addSubview:appView];
43         
44         //// 3.3.设置frame
45         int row = index / totalColumns;
46         int col = index % totalColumns;
47         // 计算x和y
48         CGFloat appX = marginX + col * (appW + marginX);
49         CGFloat appY = 30 + row * (appH + marginY);
50         appView.frame = CGRectMake(appX, appY, appW, appH);
51         
52         //3.4设置数据
53         TXApp *app = self.apps[index];
54         
55         //3.4.1设置图标
56         appView.iconView.image = [UIImage imageNamed:app.icon];
57         //3.4.2设置名称
58         appView.namelable.text = app.name;
59         //设置数据放到view里面进行
60     
61     }
62     
63     
64 }
65 -(NSArray *)apps
66 {
67     if (_apps ==nil) {
68         //初始化
69         
70         //1.获取plist的全路径
71         NSString *path = [[NSBundle mainBundle] pathForResource:@"app.plist" ofType:nil];
72         
73         //2.加载数组
74        NSArray *dictArray  = [NSArray arrayWithContentsOfFile:path];
75         //将dictArray里面所有的字典转成模型对象,方到新的数组中
76         NSMutableArray * appArray = [NSMutableArray array];
77         for (NSDictionary *dict in dictArray) {
78             //创建模型对象
79             TXApp *app = [TXApp appWithDict:dict];
80             
81             //把模型对象放到数组中
82             
83             [appArray addObject:app];
84             
85             
86             
87         }
88         _apps = appArray;
89         
90     }
91     return _apps;
92 }
93 
94 
95 - (void)didReceiveMemoryWarning
96 {
97     [super didReceiveMemoryWarning];
98     // Dispose of any resources that can be recreated.
99 }

2.对1进行优化(把数据呈现部分封装到视图)

说明:在1的基础上寻找还会有那些可以优化的部分

1)改进思路:

(1)1中主文件的66~67行对控件属性的设置能否拿到视图中进行?

(2)1中61~62行是从xib文件中读取信息的操作,且和主控制器没有什么太大的关联,能否把它也封装到视图中进行?

(3)当上述两个步骤完成后,主文件69行以后的按钮操作和按钮单击事件就显得很突兀,放在主控制器中已经不再合适,是否可以把它放到视图中进行处理

2)按照上述思路优化后的代码如下:

  优化视图,在视图部分之对外提供一个接口,把数据的处理封装在内部

3.对2进一步优化(把数据处理部分拿到模型中去进行)

(1)思路:把字典转模型部分的数据处理操作,拿到模型中去处理,这样外界不需要再关心数据处理的内部细节。

(2)优化后的代码如下

TXAppView.m文件中的数据处理

 1 #import "TXAppView.h"
 2 #import "TXApp.h"
 3 @implementation TXAppView
 4 
 5 - (id)initWithFrame:(CGRect)frame
 6 {
 7     self = [super initWithFrame:frame];
 8     if (self) {
 9         // Initialization code
10     }
11     return self;
12 }
13 
14 +(instancetype)appViewWithApp:(TXApp *)app
15 {
16     NSBundle *bundle = [NSBundle mainBundle];
17     //读取xib文件(会创建xib中描述的所有对象,并且安顺序放到数组中
18     NSArray *objs= [bundle loadNibNamed:@"TXAppView" owner:nil
19                                 options:nil];
20     TXAppView * appView = [objs lastObject];
21     appView.app =app;
22     return appView;
23 }
24 /**
25  *  从写set方法,设计内部控件的数据
26  *
27  *  @param 用传如的模型设置数据
28  */
29 -(void)setApp:(TXApp *)app
30 {
31     _app = app;
32     //1.设置图标
33      self.iconView.image = [UIImage imageNamed:app.icon];
34      // 2.设置名称
35     self.namelable.text = app.name;
36 }
37 @end

实现效果:

4.补充说明

 View的封装思路

(1) 如果一个view内部的子控件比较多,一般会考虑自定义一个view,把它内部子控件的创建屏蔽起来,不让外界关心

(2) 外界可以传入对应的模型数据给view,view拿到模型数据后给内部的子控件设置对应的数据

三、mvc机制简单说明

说明:

(1)在开发过程中,作为控制器处理的量级应该很轻,不该操心的不操心。协调好模型和视图就ok了,要学会当一个好老板。

(2)三个部分各司其职,数据模型只负责数据的处理,视图部分只负责把拿到的数据进行显示,两个部分都是被动的,等待着大管家控制器的调遣。

(3)在OC中,如果视图和数据模型之间有通道,那控制器是否处于失控状态呢?

原文地址:https://www.cnblogs.com/asd5551680/p/4068396.html