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

來源:互聯網
上載者:User

標籤:

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

一、要求

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

 

二、一步步對代碼進行最佳化

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

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

(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 : NSObject12 @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 /**Factory 方法*/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 @end15 @implementation YYappInfo16 -(instancetype)initWithDict:(NSDictionary *)dict17 {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 *)dict26 {27     return [[self alloc]initWithDict:dict];28 }29 30 -(UIImage *)img31 {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 : UIView12 @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 @end16 17 //開發思路18 //1.載入plist檔案(字典轉模型提供介面)19 //2.使用xib檔案完成單個的view20 //3.計算座標,使用for迴圈把view展現到介面上21 //4.最佳化代碼22 @implementation YYViewController23 24 //get方法,懶載入25 -(NSArray *)apps26 {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)viewDidLoad41 {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 *)btn75 {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 : UIView12 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 @end19 @implementation YYappInfoView20 21 +(instancetype)appInfoView22 {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 *)appinfo29 {30     YYappInfoView *appInfoView=[self appInfoView];31     appInfoView.appinfo=appinfo;32     return appInfoView;33 }34 35 -(void)setAppinfo:(YYappInfo *)appinfoc36 {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 @end16 @implementation YYViewController17 18 -(NSArray *)apps19 {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)viewDidLoad34 {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 : NSObject12 @property(nonatomic,copy)NSString *name;13 @property(nonatomic,copy)NSString *icon;14 @property(nonatomic,strong)UIImage *img;15 16 -(instancetype)initWithDict:(NSDictionary *)dict;17 /**Factory 方法*/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 @end12 @implementation YYappInfo13 -(instancetype)initWithDict:(NSDictionary *)dict14 {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 *)dict23 {24     return [[self alloc]initWithDict:dict];25 }26 27 -(UIImage *)img28 {29     _img=[UIImage imageNamed:self.icon];30     return _img;31 }32 33 //把資料處理部分拿到模型中來處理34 +(NSArray *)appinfoarray35 {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 @end16 @implementation YYViewController17 18 -(NSArray *)apps19 {20     if (!_apps) {21         _apps=[YYappInfo appinfoarray];22     }23     return _apps;24 }25 26 - (void)viewDidLoad27 {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拿到模型資料後給內部的子控制項設定對應的資料

三、mvc機制簡單說明

 

說明:

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

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

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

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

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.