首页 > 代码库 > 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