[注意]转载请注明出处:http://www.VEVb.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.VEVb.com/hukezhu/*/11 @interface KZAppModel : NSObject12 /**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 KZAppModel12 /*吃唐僧肉的小悟空-转载请注明出处http://www.VEVb.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 //注意此处是self29 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.VEVb.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 // //从模型对象中取出数据name100 // 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.VEVb.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.VEVb.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 //方法27 //bundle参数可以为nil,默认就是main bundle8 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进行封装.
新闻热点
疑难解答