[注意]转载请注明出处:http://www.cnblogs.com/hukezhu/
上篇文章是使用了字典转模型的方法实现的,本篇引入一个新的概念xib(描述局部界面的文件)(相对于storyboard描述全局界面来说).
使用xib可以使用可视化界面开发来代替完全代码开发.(当然这不是绝对的,一般实际开发中会结合使用).
xib文件的加载过程:
0> 根据路径, 搜索对应的xib文件(nib文件)
1> 加载xib文件的时候, 会按顺序加载xib文件中的每个控件。
2> 对于每个控件, 创建的时候都会查找对应的Class属性中配置的是那个类, 那么就创建对应的类的对象。
3> 获取到某个视图以后, 按照在xib中配置的属性的值, 放在数组中,
4> 最后返回一个数组, 这个数组中包含创建的所有元素对象。
使用xib封装一个自定义view的步骤
1> 新建一个AppView.xib文件来描述AppView内部的结构
2> 新建一个继承UIView的自定义view,假设类名叫做(appView)
3> 修改UIView的类型为appView真实类型
4> 将内部的子控件跟appView进行属性连线
5> appView提供一个模型属性
6> 重写模型属性的set方法,因为在set方法中可以拿到外界控制器传递的模型数据
7> 把模型数据拆开,分别设置数据到对应的子控件中
补充:提供一个创建AppView的类方法,将读取xib文件的代码屏蔽起来
xib文件的创建过程:
xcode界面下,commond+ N--->ios--->Users interface--->view---->create如下图:
附上源代码:
KZAppView.h
1 // 2 // KZAppModel.h 3 // UI基础-03-05-14 4 // 5 // Created by hukezhu on 15/5/15. 6 // 7 // 8 9 #import <Foundation/Foundation.h> 10 /*吃唐僧肉的小悟空-转载请注明出处http://www.cnblogs.com/hukezhu/*/ 11 @interface KZAppModel : NSObject 12 /** 13 * 应用图标 14 */ 15 @property (nonatomic ,copy) NSString *icon; 16 /** 17 * 应用名称 18 */ 19 @property (nonatomic ,copy) NSString *name; 20 21 /** 22 * 通过字典来初始化对象 23 * 24 * @param dict 字典对象 25 * 26 * @return 已经初始化完毕的模型对象 27 */ 28 - (instancetype)initWithDict:(NSDictionary *)dict; 29 30 //类方法 31 + (instancetype)appWithModelDict:(NSDictionary *)dict; 32 33 @end
KZAppView.m
1 // 2 // KZAppModel.m 3 // UI基础-03-05-14 4 // 5 // Created by hukezhu on 15/5/15. 6 // 7 // 8 9 #import "KZAppModel.h" 10 11 @implementation KZAppModel 12 /*吃唐僧肉的小悟空-转载请注明出处http://www.cnblogs.com/hukezhu/*/ 13 //对象方法 14 -(instancetype)initWithDict:(NSDictionary *)dict{ 15 16 //重写构造方法的默认写法 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 //注意此处是self 29 return [[self alloc]initWithDict:dict]; 30 } 31 @end
ViewController.m
1 // 2 // ViewController.m 3 // 03-应用管理 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 //每一行的应用的个数 22 int totalCol = 3; 23 /*吃唐僧肉的小悟空-转载请注明出处http://www.cnblogs.com/hukezhu/*/ 24 25 //添加一个小的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 //计算行号和列号 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 //首先拿到一个格子视图 49 UIView *appView = [[NSBundle mainBundle]loadNibNamed:@"KZAppView" owner:nil options:nil][0]; 50 51 //1.2设置frame 52 appView.frame = CGRectMake(appX, appY, appW, appH); 53 //1.3设置背景色(便于代码阶段验证,之后会删除) 54 //appView.backgroundColor = [UIColor redColor]; 55 //1.4将这个appView添加到view中 56 [self.view addSubview:appView]; 57 58 //加载数据 59 //NSDictionary *dict = self.apps[i]; 60 //将数据赋值给模型对象 61 KZAppModel *appModel = self.apps[i]; 62 63 64 //通过数组的特性拿到里面的小控件,进行赋值 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 // //从模型对象中取出数据 85 // imageView.image = [UIImage imageNamed:appModel.icon]; 86 // [appView addSubview:imageView]; 87 // 88 // 89 // //3.添加应用名称 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 // //从模型对象中取出数据name 100 // label.text = appModel.name; 101 // 102 // //设置字体大小 103 // label.font = [UIFont systemFontOfSize:13]; 104 // //设置字体居中 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 // //设置背景图片 118 // [downloadBtn setBackgroundImage:[UIImage imageNamed:@"buttongreen"] forState:UIControlStateNormal]; 119 // [downloadBtn setBackgroundImage:[UIImage imageNamed:@"buttongreen_highlighted"] forState:UIControlStateHighlighted]; 120 // //设置字体第一种方法 121 // [downloadBtn setTitle:@"下载" forState:UIControlStateNormal]; 122 // 123 // //设置字体第二种方法(不推荐使用) 124 // downloadBtn.titleLabel.text = @"下载"; 125 // 126 // //设置字体大小 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 /*吃唐僧肉的小悟空-转载请注明出处http://www.cnblogs.com/hukezhu/*/ 140 /** 141 * 按钮的点击方法 142 * 143 * @param btn 将按钮本身传入方法中,哪个按钮被点击就调用这个方法 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 //设置字体颜色 159 label.textColor = [UIColor redColor]; 160 //设置字体居中 161 label.textAlignment = NSTextAlignmentCenter; 162 //设置 背景色 163 label.backgroundColor = [UIColor blackColor]; 164 165 //设置圆角的半径 166 label.layer.cornerRadius = 8; 167 //将多余的部分减掉 168 label.layer.masksToBounds = YES; 169 //设置透明度 170 label.alpha = 0.0; 171 //将label添加到view中 172 [self.view addSubview:label]; 173 //使用block动画,动画持续时间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 //上面将透明度设置为0,界面上已经不显示这个label,但是它仍然在内存中,所以为了节约内存,仍要将其从内存中删除 182 [label removeFromSuperview]; 183 184 }]; 185 } 186 }]; 187 188 } 189 /** 190 * "懒加载",加载应用数据 191 * 192 */ 193 - (NSArray *)apps{ 194 195 //如果_apps为空,才加载数据 196 if (_apps == nil) { 197 //获取plist的全路径 198 NSString *path = [[NSBundle mainBundle]pathForResource:@"app.plist" ofType:nil]; 199 200 //加载数组 201 NSArray *dictArray = [NSArray arrayWithContentsOfFile:path]; 202 203 //创建一个可变数组,来动态接收模型对象 204 NSMutableArray *array = [NSMutableArray array]; 205 206 //通过循环,将字典数组的字典取出,转成模型对象 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 /*吃唐僧肉的小悟空-转载请注明出处http://www.cnblogs.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 //这个方法会创建xib中的所有对象,并且将对象按顺序放到objs数组中 4 5 6 //方法2 7 //bundle参数可以为nil,默认就是main bundle 8 UINib *nib = [UINib nibWithNibName:@"KZAppView" bundle:[NSBundle mainBundle]]; 9 NSArray *objs = [nib instantiateWithOwner:nil options:nil];
获取xib中的控件有两种方式:
1.通过绑定tag来实现
2.利用subviews[index];的特性实现
注意:两种方式都需要强制类型转换
总结:分析本文中的实现代码,在控制器中使用了xib进行赋值,当然在这里只有一个控制器,假设开发过程中有多个控制器,每个控制器都要使用这个xib,那么每个控制器都要使用这些赋值语句在各自的控制器中实现,假设以后要增加控件或者修改,则需要在每个控制器中都要修改,不利于扩展,所以我们考虑将xib进行封装,使用xib时直接调用即可,假设有修改时,直接修改xib封装的文件,对于调用者没有影响.如下图:
所以,下篇文章再次进行改进,将xib进行封装.