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

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 : NSObject10 /**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 TXApp11 -(instancetype)initWithDict:(NSDictionary *)dict12 {13     if (self = [super init]) {14         self.name = dict[@"name"];15         self.icon = dict[@"icon"];16     }17     return self;18 }19 +(instancetype)appWithDict:(NSDictionary *)dict20 {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  *  通过模型数据来创建一个view12  */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 @end12 13 @implementation TXViewController14 15 - (void)viewDidLoad16 {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* 应用宽度)/429     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.创建view36         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添加view42         [self.view addSubview:appView];43         44         //// 3.3.设置frame45         int row = index / totalColumns;46         int col = index % totalColumns;47         // 计算x和y48         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 *)apps66 {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)didReceiveMemoryWarning96 {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 code10     }11     return self;12 }13 14 +(instancetype)appViewWithApp:(TXApp *)app15 {16     NSBundle *bundle = [NSBundle mainBundle];17     //读取xib文件(会创建xib中描述的所有对象,并且安顺序放到数组中18     NSArray *objs= [bundle loadNibNamed:@"TXAppView" owner:nil19                                 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 *)app30 {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中,如果视图和数据模型之间有通道,那控制器是否处于失控状态呢?

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