一、要求
要求完成下面一個小的應用程序。
二、一步步對代碼進行優化
注意:在開發過程中,優化的過程是一步一步進行的。(如果一個人要吃五個包子才能吃飽,那麼他是否直接吃第五個,前面四個不用吃就飽了?)
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 : 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