[注意]轉(zhuǎn)載請(qǐng)注明出處:http://www.survivalescaperooms.com/hukezhu/
上篇文章是使用了字典轉(zhuǎn)模型的方法實(shí)現(xiàn)的,本篇引入一個(gè)新的概念xib(描述局部界面的文件)(相對(duì)于storyboard描述全局界面來說).
使用xib可以使用可視化界面開發(fā)來代替完全代碼開發(fā).(當(dāng)然這不是絕對(duì)的,一般實(shí)際開發(fā)中會(huì)結(jié)合使用).
xib文件的加載過程:
0> 根據(jù)路徑, 搜索對(duì)應(yīng)的xib文件(nib文件)
1> 加載xib文件的時(shí)候, 會(huì)按順序加載xib文件中的每個(gè)控件。
2> 對(duì)于每個(gè)控件, 創(chuàng)建的時(shí)候都會(huì)查找對(duì)應(yīng)的Class屬性中配置的是那個(gè)類, 那么就創(chuàng)建對(duì)應(yīng)的類的對(duì)象。
3> 獲取到某個(gè)視圖以后, 按照在xib中配置的屬性的值, 放在數(shù)組中,
4> 最后返回一個(gè)數(shù)組, 這個(gè)數(shù)組中包含創(chuàng)建的所有元素對(duì)象。
使用xib封裝一個(gè)自定義view的步驟
1> 新建一個(gè)AppView.xib文件來描述AppView內(nèi)部的結(jié)構(gòu)
2> 新建一個(gè)繼承UIView的自定義view,假設(shè)類名叫做(appView)
3> 修改UIView的類型為appView真實(shí)類型
4> 將內(nèi)部的子控件跟appView進(jìn)行屬性連線
5> appView提供一個(gè)模型屬性
6> 重寫模型屬性的set方法,因?yàn)樵趕et方法中可以拿到外界控制器傳遞的模型數(shù)據(jù)
7> 把模型數(shù)據(jù)拆開,分別設(shè)置數(shù)據(jù)到對(duì)應(yīng)的子控件中
補(bǔ)充:提供一個(gè)創(chuàng)建AppView的類方法,將讀取xib文件的代碼屏蔽起來
xib文件的創(chuàng)建過程:
xcode界面下,commond+ N--->ios--->Users interface--->view---->create如下圖:


附上源代碼:
KZAppView.h
1 // 2 // KZAppModel.h 3 // UI基礎(chǔ)-03-05-14 4 // 5 // Created by hukezhu on 15/5/15. 6 // 7 // 8 9 #import <Foundation/Foundation.h>10 /*吃唐僧肉的小悟空-轉(zhuǎn)載請(qǐng)注明出處http://www.survivalescaperooms.com/hukezhu/*/11 @interface KZAppModel : NSObject12 /**13 * 應(yīng)用圖標(biāo)14 */15 @PRoperty (nonatomic ,copy) NSString *icon;16 /**17 * 應(yīng)用名稱18 */19 @property (nonatomic ,copy) NSString *name;20 21 /**22 * 通過字典來初始化對(duì)象23 *24 * @param dict 字典對(duì)象25 *26 * @return 已經(jīng)初始化完畢的模型對(duì)象27 */28 - (instancetype)initWithDict:(NSDictionary *)dict;29 30 //類方法31 + (instancetype)appWithModelDict:(NSDictionary *)dict;32 33 @end
KZAppView.m
1 // 2 // KZAppModel.m 3 // UI基礎(chǔ)-03-05-14 4 // 5 // Created by hukezhu on 15/5/15. 6 // 7 // 8 9 #import "KZAppModel.h"10 11 @implementation KZAppModel12 /*吃唐僧肉的小悟空-轉(zhuǎn)載請(qǐng)注明出處http://www.survivalescaperooms.com/hukezhu/*/13 //對(duì)象方法14 -(instancetype)initWithDict:(NSDictionary *)dict{15 16 //重寫構(gòu)造方法的默認(rèn)寫法17 if(self = [super init]){18 19 //將字典的所有屬性賦值給模型20 self.icon = dict[@"icon"];21 self.name = dict[@"name"];22 }23 return self;24 }25 //類方法26 +(instancetype)appWithModelDict:(NSDictionary *)dict{27 28 //注意此處是self29 return [[self alloc]initWithDict:dict];30 }31 @end
ViewController.m
1 // 2 // ViewController.m 3 // 03-應(yīng)用管理 4 // 5 // Created by hukezhu on 15/5/14. 6 // 7 // 8 9 #import "ViewController.h" 10 #import "KZAppModel.h" 11 12 @interface ViewController () 13 @property (nonatomic,strong)NSArray *apps; 14 @end 15 16 @implementation ViewController 17 18 - (void)viewDidLoad { 19 [super viewDidLoad]; 20 21 //每一行的應(yīng)用的個(gè)數(shù) 22 int totalCol = 3; 23 /*吃唐僧肉的小悟空-轉(zhuǎn)載請(qǐng)注明出處http://www.survivalescaperooms.com/hukezhu/*/ 24 25 //添加一個(gè)小的view 26 CGFloat appW = 80; 27 CGFloat appH = 100; 28 CGFloat marginX = 20; 29 CGFloat marginY = 20; 30 CGFloat hightMargin = 30; 31 CGFloat leftMargin = (self.view.frame.size.width - totalCol * appW - (totalCol - 1) *marginX)* 0.5; 32 33 34 35 for (int i = 0; i < self.apps.count; i++) { 36 37 38 //計(jì)算行號(hào)和列號(hào) 39 int row = i / totalCol; 40 int col = i % totalCol; 41 42 CGFloat appX = leftMargin + (marginX + appW)* col; 43 CGFloat appY = hightMargin + (marginY + appH)* row; 44 45 //1.添加view 46 47 48 //首先拿到一個(gè)格子視圖 49 UIView *appView = [[NSBundle mainBundle]loadNibNamed:@"KZAppView" owner:nil options:nil][0]; 50 51 //1.2設(shè)置frame 52 appView.frame = CGRectMake(appX, appY, appW, appH); 53 //1.3設(shè)置背景色(便于代碼階段驗(yàn)證,之后會(huì)刪除) 54 //appView.backgroundColor = [UIColor redColor]; 55 //1.4將這個(gè)appView添加到view中 56 [self.view addSubview:appView]; 57 58 //加載數(shù)據(jù) 59 //NSDictionary *dict = self.apps[i]; 60 //將數(shù)據(jù)賦值給模型對(duì)象 61 KZAppModel *appModel = self.apps[i]; 62 63 64 //通過數(shù)組的特性拿到里面的小控件,進(jìn)行賦值 65 UIImageView *imageView = (UIImageView *)appView.subviews[0]; 66 imageView.image = [UIImage imageNamed:appModel.icon]; 67 68 UILabel *label = appView.subviews[1]; 69 label.text = appModel.name; 70 71 UIButton *downBtn = (UIButton *)appView.subviews[2]; 72 [downBtn addTarget:self action:@selector(btnOnClick:) forControlEvents:UIControlEventTouchUpInside]; 73 74 75 // //2.添加圖片UIImageView 76 // CGFloat imageW = 60; 77 // CGFloat imageH = 50; 78 // CGFloat imageX = (appW - imageW)*0.5; 79 // CGFloat imageY = 0; 80 // UIImageView *imageView = [[UIImageView alloc]init]; 81 // imageView.frame = CGRectMake(imageX, imageY, imageW, imageH); 82 // //imageView.backgroundColor = [UIColor blueColor]; 83 // //imageView.image = [UIImage imageNamed:dict[@"icon"]]; 84 // //從模型對(duì)象中取出數(shù)據(jù) 85 // imageView.image = [UIImage imageNamed:appModel.icon]; 86 // [appView addSubview:imageView]; 87 // 88 // 89 // //3.添加應(yīng)用名稱 90 // 91 // CGFloat labelW = 80; 92 // CGFloat labelH = 25; 93 // CGFloat labelX = 0; 94 // CGFloat labelY = imageH; 95 // UILabel *label = [[UILabel alloc]init]; 96 // label.frame = CGRectMake(labelX, labelY, labelW, labelH); 97 // //label.backgroundColor = [UIColor grayColor]; 98 // //label.text = dict[@"name"]; 99 // //從模型對(duì)象中取出數(shù)據(jù)name100 // label.text = appModel.name;101 // 102 // //設(shè)置字體大小103 // label.font = [UIFont systemFontOfSize:13];104 // //設(shè)置字體居中105 // label.textAlignment = NSTextAlignmentCenter;106 // [appView addSubview:label];107 // 108 // //4.添加下載按鈕109 // 110 // CGFloat downloadW = 60;111 // CGFloat downloadH = 25;112 // CGFloat downloadX = 10;113 // CGFloat downloadY = labelH + labelY;114 // UIButton *downloadBtn = [[UIButton alloc]init];115 // downloadBtn.frame = CGRectMake(downloadX, downloadY, downloadW, downloadH);116 // //downloadBtn.backgroundColor = [UIColor yellowColor];117 // //設(shè)置背景圖片118 // [downloadBtn setBackgroundImage:[UIImage imageNamed:@"buttongreen"] forState:UIControlStateNormal];119 // [downloadBtn setBackgroundImage:[UIImage imageNamed:@"buttongreen_highlighted"] forState:UIControlStateHighlighted];120 // //設(shè)置字體第一種方法121 // [downloadBtn setTitle:@"下載" forState:UIControlStateNormal];122 // 123 // //設(shè)置字體第二種方法(不推薦使用)124 // downloadBtn.titleLabel.text = @"下載";125 // 126 // //設(shè)置字體大小127 // downloadBtn.titleLabel.font = [UIFont systemFontOfSize:15];128 // [appView addSubview:downloadBtn];129 // 130 // 131 // [downloadBtn addTarget:self action:@selector(btnOnClick:) forControlEvents:UIControlEventTouchUpInside];132 }133 134 135 136 137 138 }139 /*吃唐僧肉的小悟空-轉(zhuǎn)載請(qǐng)注明出處http://www.survivalescaperooms.com/hukezhu/*/140 /**141 * 按鈕的點(diǎn)擊方法142 *143 * @param btn 將按鈕本身傳入方法中,哪個(gè)按鈕被點(diǎn)擊就調(diào)用這個(gè)方法144 */145 - (void)btnOnClick:(UIButton *)btn{146 147 //NSLog(@"------%@",btn);148 btn.enabled = NO;149 [btn setTitle:@"已下載" forState:UIControlStateNormal];150 151 CGFloat labelW = 120;152 CGFloat labelH = 30;153 CGFloat labelX = (self.view.frame.size.width - labelW)* 0.5;154 CGFloat labelY = (self.view.frame.size.height - labelH)*0.5;155 UILabel *label = [[UILabel alloc]init];156 label.frame = CGRectMake(labelX, labelY, labelW, labelH);157 label.text = @"正在下載";158 //設(shè)置字體顏色159 label.textColor = [UIColor redColor];160 //設(shè)置字體居中161 label.textAlignment = NSTextAlignmentCenter;162 //設(shè)置 背景色163 label.backgroundColor = [UIColor blackColor];164 165 //設(shè)置圓角的半徑166 label.layer.cornerRadius = 8;167 //將多余的部分減掉168 label.layer.masksToBounds = YES;169 //設(shè)置透明度170 label.alpha = 0.0;171 //將label添加到view中172 [self.view addSubview:label];173 //使用block動(dòng)畫,動(dòng)畫持續(xù)時(shí)間2秒174 [UIView animateWithDuration:2.0 animations:^{175 label.alpha = 0.5;176 } completion:^(BOOL finished) {177 if (finished) {178 [UIView animateWithDuration:2.0 delay:0.1 options:UIViewAnimationOptionCurveLinear animations:^{179 label.alpha = 0.0;180 } completion:^(BOOL finished) {181 //上面將透明度設(shè)置為0,界面上已經(jīng)不顯示這個(gè)label,但是它仍然在內(nèi)存中,所以為了節(jié)約內(nèi)存,仍要將其從內(nèi)存中刪除182 [label removeFromSuperview];183 184 }];185 }186 }];187 188 }189 /**190 * "懶加載",加載應(yīng)用數(shù)據(jù)191 *192 */193 - (NSArray *)apps{194 195 //如果_apps為空,才加載數(shù)據(jù)196 if (_apps == nil) {197 //獲取plist的全路徑198 NSString *path = [[NSBundle mainBundle]pathForResource:@"app.plist" ofType:nil];199 200 //加載數(shù)組201 NSArray *dictArray = [NSArray arrayWithContentsOfFile:path];202 203 //創(chuàng)建一個(gè)可變數(shù)組,來動(dòng)態(tài)接收模型對(duì)象204 NSMutableArray *array = [NSMutableArray array];205 206 //通過循環(huán),將字典數(shù)組的字典取出,轉(zhuǎn)成模型對(duì)象207 for (NSDictionary *dict in dictArray) {208 KZAppModel *appModel = [KZAppModel appWithModelDict:dict];209 [array addObject:appModel];210 }211 _apps = array;212 }213 return _apps;214 /*吃唐僧肉的小悟空-轉(zhuǎn)載請(qǐng)注明出處http://www.survivalescaperooms.com/hukezhu/*/215 }216 217 - (void)didReceiveMemoryWarning {218 [super didReceiveMemoryWarning];219 // Dispose of any resources that can be recreated.220 }221 222 @end
xib文件加載的兩種方式:
1 //方法1:2 NSArray *objs = [[NSBundle mainBundle] loadNibNamed:@"KZAppView" owner:nil options:nil];3 //這個(gè)方法會(huì)創(chuàng)建xib中的所有對(duì)象,并且將對(duì)象按順序放到objs數(shù)組中4 5 6 //方法27 //bundle參數(shù)可以為nil,默認(rèn)就是main bundle8 UINib *nib = [UINib nibWithNibName:@"KZAppView" bundle:[NSBundle mainBundle]];9 NSArray *objs = [nib instantiateWithOwner:nil options:nil];
獲取xib中的控件有兩種方式:
1.通過綁定tag來實(shí)現(xiàn)
2.利用subviews[index];的特性實(shí)現(xiàn)
注意:兩種方式都需要強(qiáng)制類型轉(zhuǎn)換
總結(jié):分析本文中的實(shí)現(xiàn)代碼,在控制器中使用了xib進(jìn)行賦值,當(dāng)然在這里只有一個(gè)控制器,假設(shè)開發(fā)過程中有多個(gè)控制器,每個(gè)控制器都要使用這個(gè)xib,那么每個(gè)控制器都要使用這些賦值語句在各自的控制器中實(shí)現(xiàn),假設(shè)以后要增加控件或者修改,則需要在每個(gè)控制器中都要修改,不利于擴(kuò)展,所以我們考慮將xib進(jìn)行封裝,使用xib時(shí)直接調(diào)用即可,假設(shè)有修改時(shí),直接修改xib封裝的文件,對(duì)于調(diào)用者沒有影響.如下圖:

所以,下篇文章再次進(jìn)行改進(jìn),將xib進(jìn)行封裝.
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注