• 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中,如果视图和数据模型之间有通道,那控制器是否处于失控状态呢?

  • 相关阅读:
    最优比率环 SPFA+二分
    严格次小生成树
    SPFA判断负环BFS+DFS
    poj 1149 PIGS 网络流-最大流 建图理解
    9.20开始的停课日常
    Speed
    [BZOJ4827][Hnoi2017]礼物(FFT)
    中山纪念中学集训日志
    [POJ1151][HDU1542]Atlantis(线段树,扫描线)
    [BZOJ2002][洛谷P3203][Hnoi2010]Bounce 弹飞绵羊(LCT维护链长)
  • 原文地址:https://www.cnblogs.com/asd5551680/p/4068396.html
Copyright © 2020-2023  润新知