iOS開發UI篇—從代碼的逐步優化看MVC

iOS開發UI篇—從代碼的逐步優化看MVC數組

1、要求mvc

要求完成下面一個小的應用程序。app

 

2、一步步對代碼進行優化ide

注意:在開發過程當中,優化的過程是一步一步進行的。(若是一我的要吃五個包子才能吃飽,那麼他是否直接吃第五個,前面四個不用吃就飽了?)優化

1.完成基本要求的代碼(使用了字典轉模型和xib連線)atom

(1)文件結構spa

(2)主要代碼3d

  字典轉模型部分:code

 YYappInfo.h頭文件orm

 1 //
 2 //  YYappInfo.h
 3 //  12-視圖改進(1)
 4 //
 5 //  Created by apple on 14-5-25.
 6 //  Copyright (c) 2014年 itcase. All rights reserved.
 7 //
 8 
 9 #import <Foundation/Foundation.h>
10 
11 @interface YYappInfo : NSObject
12 @property(nonatomic,copy)NSString *name;
13 @property(nonatomic,copy)NSString *icon;
14 @property(nonatomic,strong,readonly)UIImage *img;
15 
16 -(instancetype)initWithDict:(NSDictionary *)dict;
17 /**工廠方法*/
18 +(instancetype)appInfoWithDict:(NSDictionary *)dict;
19 @end

YYappInfo.m文件

 1 //
 2 //  YYappInfo.m
 3 //  12-視圖改進(1)
 4 //
 5 //  Created by apple on 14-5-25.
 6 //  Copyright (c) 2014年 itcase. All rights reserved.
 7 //
 8 
 9 #import "YYappInfo.h"
10 @interface YYappInfo()
11 {
12     UIImage *_img;
13 }
14 @end
15 @implementation YYappInfo
16 -(instancetype)initWithDict:(NSDictionary *)dict
17 {
18     if (self=[super init]) {
19         self.name=dict[@"name"];
20         self.icon=dict[@"icon"];
21     }
22     return self;
23 }
24 
25 +(instancetype)appInfoWithDict:(NSDictionary *)dict
26 {
27     return [[self alloc]initWithDict:dict];
28 }
29 
30 -(UIImage *)img
31 {
32     _img=[UIImage imageNamed:self.icon];
33     return _img;
34 }
35 @end

 xib部分(YYappInfoView.h文件):

注:(xib視圖和YYappInfoView進行了關聯,三個屬性均進行了連線)  

 1 //
 2 //  YYappInfoView.h
 3 //  12-視圖改進(1)
 4 //
 5 //  Created by apple on 14-5-25.
 6 //  Copyright (c) 2014年 itcase. All rights reserved.
 7 //
 8 
 9 #import <UIKit/UIKit.h>
10 
11 @interface YYappInfoView : UIView
12 @property (strong, nonatomic) IBOutlet UIImageView *appInfoViewimg;
13 
14 @property (strong ,nonatomic) IBOutlet UILabel *appInfoViewlab;
15 @property (strong, nonatomic) IBOutlet UIButton *appInfoViewbtn;
16 
17 @end

主要功能實現部分:

YYViewController.m文件

 1 //
 2 //  YYViewController.m
 3 //  12-視圖改進(1)
 4 //
 5 //  Created by apple on 14-5-25.
 6 //  Copyright (c) 2014年 itcase. All rights reserved.
 7 //
 8 
 9 #import "YYViewController.h"
10 #import "YYappInfo.h"
11 #import "YYappInfoView.h"
12 
13 @interface YYViewController ()
14 @property(nonatomic,strong)NSArray *apps;
15 @end
16 
17 //開發思路
18 //1.加載plist文件(字典轉模型提供接口)
19 //2.使用xib文件完成單個的view
20 //3.計算座標,使用for循環把view展示到界面上
21 //4.優化代碼
22 @implementation YYViewController
23 
24 //get方法,懶加載
25 -(NSArray *)apps
26 {
27     if (!_apps) {
28         NSString *path = [[NSBundle mainBundle]pathForResource:@"app.plist" ofType:nil];
29         NSArray * arrayM = [NSArray arrayWithContentsOfFile:path];
30         
31         NSMutableArray *appinfoarray=[NSMutableArray array];
32         for (NSDictionary *dict in arrayM) {
33             [appinfoarray addObject:[YYappInfo appInfoWithDict:dict]];
34         }
35         _apps = appinfoarray;
36     }
37     return _apps;
38 }
39 
40 - (void)viewDidLoad
41 {
42     [super viewDidLoad];
43     NSLog(@"%d",self.apps.count);
44     
45     int totalloc = 3;
46     CGFloat appviewW = 80;
47     CGFloat appviewH = 90;
48     CGFloat margin = (self.view.frame.size.width-totalloc*appviewW)/(totalloc+1);
49     
50     int count=self.apps.count;
51     for (int i = 0; i < count; i++) {
52         int row = i/totalloc;
53         int loc = i%totalloc;
54         
55         CGFloat appviewX = margin + (margin + appviewW) * loc;
56         CGFloat appviewY =  margin + (margin + appviewH) * row;
57         
58           YYappInfo *appinfo=self.apps[i];
59         
60         //拿出xib中的數據
61         NSArray *arryM=[[NSBundle mainBundle]loadNibNamed:@"appInfoxib" owner:nil options:nil];
62         YYappInfoView *appinfoview=[arryM firstObject];
63         //設置位置
64         appinfoview.frame=CGRectMake(appviewX, appviewY, appviewW, appviewH);
65         //設置值
66         appinfoview.appInfoViewimg.image=appinfo.img;
67         appinfoview.appInfoViewlab.text=appinfo.name;
68         //添加到視圖
69         appinfoview.appInfoViewbtn.tag=i;
70         [appinfoview.appInfoViewbtn addTarget:self action:@selector(Click:) forControlEvents:UIControlEventTouchUpInside];
71         [self.view addSubview:appinfoview];
72     }
73 }
74 -(void)Click:(UIButton *)btn
75 {
76     btn.enabled=NO;
77     YYappInfo *appinfo=self.apps[btn.tag];
78     UILabel *lab=[[UILabel alloc]initWithFrame:CGRectMake(60, 450, 200, 20)];
79     [lab setBackgroundColor:[UIColor lightGrayColor]];
80     [lab setTextAlignment:NSTextAlignmentCenter];
81     [lab setText:[NSString stringWithFormat:@"%@成功下載",appinfo.name]];
82     [self.view addSubview:lab];
83     
84     lab.alpha=1.0;
85     [UIView animateWithDuration:2.0 animations:^{
86         lab.alpha=0;
87     }completion:^(BOOL finished) {
88         [lab removeFromSuperview];
89     }];
90 }
91 @end

2.對1進行優化(把數據呈現部分封裝到視圖)

說明:在1的基礎上尋找還會有那些能夠優化的部分

1)改進思路:

(1)1中主文件的66~67行對控件屬性的設置可否拿到視圖中進行?

(2)1中61~62行是從xib文件中讀取信息的操做,且和主控制器沒有什麼太大的關聯,可否把它也封裝到視圖中進行?

(3)當上述兩個步驟完成後,主文件69行之後的按鈕操做和按鈕單擊事件就顯得很突兀,放在主控制器中已經再也不合適,是否能夠把它放到視圖中進行處理

2)按照上述思路優化後的代碼以下:

  優化視圖,在視圖部分之對外提供一個接口,把數據的處理封裝在內部

YYappInfoView.h文件代碼:

 1 //
 2 //  YYappInfoView.h
 3 //  12-視圖改進(1)
 4 //
 5 //  Created by apple on 14-5-25.
 6 //  Copyright (c) 2014年 itcase. All rights reserved.
 7 //
 8 
 9 #import <UIKit/UIKit.h>
10 @class YYappInfo;
11 @interface YYappInfoView : UIView
12 
13 //讀取
14 //+(instancetype)appInfoView;
15 //只對外開放一個數據接口
16 +(instancetype)appInfoViewWithappInfo:(YYappInfo *)appinfo;
17 @end

YYappInfoView.m文件代碼

說明:該文件中的屬性和click等均已作了連線的操做。

 1 //
 2 //  YYappInfoView.m
 3 //  12-視圖改進(1)
 4 //
 5 //  Created by apple on 14-5-25.
 6 //  Copyright (c) 2014年 itcase. All rights reserved.
 7 //
 8 
 9 #import "YYappInfoView.h"
10 #import "YYappInfo.h"
11 //私有擴展,把屬性拿進來
12 @interface YYappInfoView ()
13 @property (strong, nonatomic) IBOutlet UIImageView *appInfoViewimg;
14 @property (strong ,nonatomic) IBOutlet UILabel *appInfoViewlab;
15 @property (strong, nonatomic) IBOutlet UIButton *appInfoViewbtn;
16 @property(strong,nonatomic)YYappInfo *appinfo;
17 
18 @end
19 @implementation YYappInfoView
20 
21 +(instancetype)appInfoView
22 {
23     NSArray *arryM=[[NSBundle mainBundle]loadNibNamed:@"appInfoxib" owner:nil options:nil];
24     YYappInfoView *appinfoview=[arryM firstObject];
25     return appinfoview;
26 }
27 
28 +(instancetype)appInfoViewWithappInfo:(YYappInfo *)appinfo
29 {
30     YYappInfoView *appInfoView=[self appInfoView];
31     appInfoView.appinfo=appinfo;
32     return appInfoView;
33 }
34 
35 -(void)setAppinfo:(YYappInfo *)appinfoc
36 {
37     //這裏必定要記錄變化
38     _appinfo=appinfoc;
39     self.appInfoViewimg.image=appinfoc.img;
    self.appInfoViewlab.text=appinfoc.name;
41 }
42 - (IBAction)Click { 43     
44     self.appInfoViewbtn.enabled=NO; 45     //YYappInfo *appinfo=self.apps[];
46     
47     YYappInfo *appinfo=self.appinfo; 48     UILabel *lab=[[UILabel alloc]initWithFrame:CGRectMake(60, 450, 200, 20)]; 49  [lab setBackgroundColor:[UIColor lightGrayColor]]; 50  [lab setTextAlignment:NSTextAlignmentCenter]; 51     [lab setText:[NSString stringWithFormat:@"%@成功下載",appinfo.name]]; 52     //把lab添加到父視圖(即view中)
53  [self.superview addSubview:lab]; 54     
55     lab.alpha=1.0; 56     [UIView animateWithDuration:2.0 animations:^{ 57         lab.alpha=0; 58     }completion:^(BOOL finished) { 59  [lab removeFromSuperview]; 60  }]; 61 } 62 
63 
64 @end

優化後的主控制器部分

YYViewController.m文件代碼

 1 //
 2 //  YYViewController.m
 3 //  12-視圖改進(1)
 4 //
 5 //  Created by apple on 14-5-25.
 6 //  Copyright (c) 2014年 itcase. All rights reserved.
 7 //
 8 
 9 #import "YYViewController.h"
10 #import "YYappInfo.h"
11 #import "YYappInfoView.h"
12 
13 @interface YYViewController ()
14 @property(nonatomic,strong)NSArray *apps;
15 @end
16 @implementation YYViewController
17 
18 -(NSArray *)apps
19 {
20     if (!_apps) {
21         NSString *path = [[NSBundle mainBundle]pathForResource:@"app.plist" ofType:nil];
22         NSArray * arrayM = [NSArray arrayWithContentsOfFile:path];
23         
24         NSMutableArray *appinfoarray=[NSMutableArray array];
25         for (NSDictionary *dict in arrayM) {
26             [appinfoarray addObject:[YYappInfo appInfoWithDict:dict]];
27         }
28         _apps = appinfoarray;
29     }
30     return _apps;
31 }
32 
33 - (void)viewDidLoad
34 {
35     [super viewDidLoad];
36     NSLog(@"%d",self.apps.count);
37     
38     int totalloc = 3;
39     CGFloat appviewW = 80;
40     CGFloat appviewH = 90;
41     CGFloat margin = (self.view.frame.size.width-totalloc*appviewW)/(totalloc+1);
42     
43     int count=self.apps.count;
44     for (int i = 0; i < count; i++) {
45         int row = i/totalloc;
46         int loc = i%totalloc;
47         
48         CGFloat appviewX = margin + (margin + appviewW) * loc;
49         CGFloat appviewY =  margin + (margin + appviewH) * row;
50         
51         /*思路:
52          要達到的效果 appinfoview.appinfo=appinfo;
53         優化後即變成  appinfoview.appinfo=self.apps[i];
54         要進行上面代碼的操做,須要在視圖中新增長一個appinfo類的屬性,這樣數據——》視圖的轉換便可以不須要在主控制器中完成,讓程序結構一目瞭然
55          */
56         YYappInfo *appinfo=self.apps[i];
57         YYappInfoView *appinfoview=[YYappInfoView appInfoViewWithappInfo:appinfo];
58         //設置位置
59         appinfoview.frame=CGRectMake(appviewX, appviewY, appviewW, appviewH);
60         //添加
61         [self.view addSubview:appinfoview];
62     }
63 }
64 @end

3.對2進一步優化(把數據處理部分拿到模型中去進行)

(1)思路:把字典轉模型部分的數據處理操做,拿到模型中去處理,這樣外界不須要再關心數據處理的內部細節。

(2)優化後的代碼以下

YYappInfo.h文件中向外開放一個接口,返回一個處理好的數組。

 1 //
 2 //  YYappInfo.h
 3 //  12-視圖改進(1)
 4 //
 5 //  Created by apple on 14-5-25.
 6 //  Copyright (c) 2014年 itcase. All rights reserved.
 7 //
 8 
 9 #import <Foundation/Foundation.h>
10 
11 @interface YYappInfo : NSObject
12 @property(nonatomic,copy)NSString *name;
13 @property(nonatomic,copy)NSString *icon;
14 @property(nonatomic,strong)UIImage *img;
15 
16 -(instancetype)initWithDict:(NSDictionary *)dict;
17 /**工廠方法*/
18 +(instancetype)appInfoWithDict:(NSDictionary *)dict;
19 +(NSArray *)appinfoarray;
20 @end

YYappInfo.m文件中的數據處理

 1 //
 2 //  YYappInfo.m
 3 //  12-視圖改進(1)
 4 //
 5 //  Created by apple on 14-5-25.
 6 //  Copyright (c) 2014年 itcase. All rights reserved.
 7 //
 8 
 9 #import "YYappInfo.h"
10 @interface YYappInfo()
11 @end
12 @implementation YYappInfo
13 -(instancetype)initWithDict:(NSDictionary *)dict
14 {
15     if (self=[super init]) {
16         self.name=dict[@"name"];
17         self.icon=dict[@"icon"];
18     }
19     return self;
20 }
21 
22 +(instancetype)appInfoWithDict:(NSDictionary *)dict
23 {
24     return [[self alloc]initWithDict:dict];
25 }
26 
27 -(UIImage *)img
28 {
29     _img=[UIImage imageNamed:self.icon];
30     return _img;
31 }
32 
33 //把數據處理部分拿到模型中來處理
34 +(NSArray *)appinfoarray
35 {
36     NSString *path = [[NSBundle mainBundle]pathForResource:@"app.plist" ofType:nil];
37     NSArray * arrayM = [NSArray arrayWithContentsOfFile:path];
38     
39     NSMutableArray *appinfoarray=[NSMutableArray array];
40     for (NSDictionary *dict in arrayM) {
41         [appinfoarray addObject:[YYappInfo appInfoWithDict:dict]];
42     }
43     return appinfoarray;
44 }
45 @end

主控制器中再也不須要關心數據處理的內部細節

YYViewController.m文件如今只是負責模型和視圖之間的協調工做了,怎麼樣?差很少了吧。

 1 //
 2 //  YYViewController.m
 3 //  12-視圖改進(1)
 4 //
 5 //  Created by apple on 14-5-25.
 6 //  Copyright (c) 2014年 itcase. All rights reserved.
 7 //
 8 
 9 #import "YYViewController.h"
10 #import "YYappInfo.h"
11 #import "YYappInfoView.h"
12 
13 @interface YYViewController ()
14 @property(nonatomic,strong)NSArray *apps;
15 @end
16 @implementation YYViewController
17 
18 -(NSArray *)apps
19 {
20     if (!_apps) {
21         _apps=[YYappInfo appinfoarray];
22     }
23     return _apps;
24 }
25 
26 - (void)viewDidLoad
27 {
28     [super viewDidLoad];
29     
30     int totalloc = 3;
31     CGFloat appviewW = 80;
32     CGFloat appviewH = 90;
33     CGFloat margin = (self.view.frame.size.width-totalloc*appviewW)/(totalloc+1);
34     
35     int count=self.apps.count;
36     for (int i = 0; i < count; i++) {
37         
38         int row = i/totalloc;
39         int loc = i%totalloc;
40         
41         CGFloat appviewX = margin + (margin + appviewW) * loc;
42         CGFloat appviewY =  margin + (margin + appviewH) * row;
43         
44         YYappInfo *appinfo=self.apps[i];
45         YYappInfoView *appinfoview=[YYappInfoView appInfoViewWithappInfo:appinfo];
46         appinfoview.frame=CGRectMake(appviewX, appviewY, appviewW, appviewH);
47         [self.view addSubview:appinfoview];
48     }
49 }
50 @end

實現效果:

 

4.補充說明

 View的封裝思路

(1) 若是一個view內部的子控件比較多,通常會考慮自定義一個view,把它內部子控件的建立屏蔽起來,不讓外界關心

(2) 外界能夠傳入對應的模型數據給view,view拿到模型數據後給內部的子控件設置對應的數據

3、mvc機制簡單說明

 

說明:

(1)在開發過程當中,做爲控制器處理的量級應該很輕,不應操心的不操心。協調好模型和視圖就ok了,要學會當一個好老闆。

(2)三個部分各司其職,數據模型只負責數據的處理,視圖部分只負責把拿到的數據進行顯示,兩個部分都是被動的,等待着大管家控制器的調遣。

(3)在OC中,若是視圖和數據模型之間有通道,那控制器是否處於失控狀態呢?

相關文章
相關標籤/搜索