[注意]转载请注明出处: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.h3//UI基础-03-05-144//5//Created by hukezhu on 15/5/15.6//7//89#import<Foundation/Foundation.h>10/*吃唐僧肉的小悟空-转载请注明出处http://www.cnblogs.com/hukezhu/*/11@interfaceKZAppModel : NSObject12/**13* 应用图标14*/15@PRoperty (nonatomic ,copy) NSString *icon;16/**17* 应用名称18*/19@property (nonatomic ,copy) NSString *name;2021/**22* 通过字典来初始化对象23*24* @param dict 字典对象25*26* @return 已经初始化完毕的模型对象27*/28- (instancetype)initWithDict:(NSDictionary *)dict;2930//类方法31+ (instancetype)appWithModelDict:(NSDictionary *)dict;3233@end
KZAppView.m
1//2//KZAppModel.m3//UI基础-03-05-144//5//Created by hukezhu on 15/5/15.6//7//89#import"KZAppModel.h"1011@implementationKZAppModel12/*吃唐僧肉的小悟空-转载请注明出处http://www.cnblogs.com/hukezhu/*/13//对象方法14-(instancetype)initWithDict:(NSDictionary *)dict{1516//重写构造方法的默认写法17if(self =[super init]){1819//将字典的所有属性赋值给模型20self.icon = dict[@"icon"];21self.name = dict[@"name"];22}23returnself;24}25//类方法26+(instancetype)appWithModelDict:(NSDictionary *)dict{2728//注意此处是self29return[[self alloc]initWithDict:dict];30}31@end
ViewController.m
1//2//ViewController.m3//03-应用管理4//5//Created by hukezhu on 15/5/14.6//7//89#import"ViewController.h"10#import"KZAppModel.h"1112@interfaceViewController ()13@property (nonatomic,strong)NSArray *apps;14@end1516@implementationViewController1718- (void)viewDidLoad {19[super viewDidLoad];2021//每一行的应用的个数22inttotalCol =3;23/*吃唐僧肉的小悟空-转载请注明出处http://www.cnblogs.com/hukezhu/*/2425//添加一个小的view26CGFloat appW =80;27CGFloat appH =100;28CGFloat marginX =20;29CGFloat marginY =20;30CGFloat hightMargin =30;31CGFloat leftMargin = (self.view.frame.size.width - totalCol * appW - (totalCol -1) *marginX)*0.5;32333435for(inti =0; i < self.apps.count; i++) {363738//计算行号和列号39introw = i /totalCol;40intcol = i %totalCol;4142CGFloat appX = leftMargin + (marginX + appW)*col;43CGFloat appY = hightMargin + (marginY + appH)*row;4445//1.添加view464748//首先拿到一个格子视图49UIView *appView = [[NSBundle mainBundle]loadNibNamed:@"KZAppView"owner:nil options:nil][0];5051//1.2设置frame52appView.frame =CGRectMake(appX, appY, appW, appH);53//1.3设置背景色(便于代码阶段验证,之后会删除)54//appView.backgroundColor = [UIColor redColor];55//1.4将这个appView添加到view中56[self.view addSubview:appView];5758//加载数据59//NSDictionary *dict = self.apps[i];60//将数据赋值给模型对象61KZAppModel *appModel =self.apps[i];626364//通过数组的特性拿到里面的小控件,进行赋值65UIImageView *imageView = (UIImageView *)appView.subviews[0];66imageView.image =[UIImage imageNamed:appModel.icon];6768UILabel *label = appView.subviews[1];69label.text =appModel.name;7071UIButton *downBtn = (UIButton *)appView.subviews[2];72[downBtn addTarget:self action:@selector(btnOnClick:) forControlEvents:UIControlEventTouchUpInside];737475////2.添加图片UIImageView76//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}133134135136137138}139/*吃唐僧肉的小悟空-转载请注明出处http://www.cnblogs.com/hukezhu/*/140/**141* 按钮的点击方法142*143* @param btn 将按钮本身传入方法中,哪个按钮被点击就调用这个方法144*/145- (void)btnOnClick:(UIButton *)btn{146147//NSLog(@"------%@",btn);148btn.enabled =NO;149[btn setTitle:@"已下载"forState:UIControlStateNormal];150151CGFloat labelW =120;152CGFloat labelH =30;153CGFloat labelX = (self.view.frame.size.width - labelW)*0.5;154CGFloat labelY = (self.view.frame.size.height - labelH)*0.5;155UILabel *label =[[UILabel alloc]init];156label.frame =CGRectMake(labelX, labelY, labelW, labelH);157label.text =@"正在下载";158//设置字体颜色159label.textColor =[UIColor redColor];160//设置字体居中161label.textAlignment =NSTextAlignmentCenter;162//设置 背景色163label.backgroundColor =[UIColor blackColor];164165//设置圆角的半径166label.layer.cornerRadius =8;167//将多余的部分减掉168label.layer.masksToBounds =YES;169//设置透明度170label.alpha =0.0;171//将label添加到view中172[self.view addSubview:label];173//使用block动画,动画持续时间2秒174[UIView animateWithDuration:2.0animations:^{175label.alpha =0.5;176} completion:^(BOOL finished) {177if(finished) {178[UIView animateWithDuration:2.0delay:0.1options:UIViewAnimationOptionCurveLinear animations:^{179label.alpha =0.0;180} completion:^(BOOL finished) {181//上面将透明度设置为0,界面上已经不显示这个label,但是它仍然在内存中,所以为了节约内存,仍要将其从内存中删除182[label removeFromSuperview];183184}];185}186}];187188}189/**190* "懒加载",加载应用数据191*192*/193- (NSArray *)apps{194195//如果_apps为空,才加载数据196if(_apps ==nil) {197//获取plist的全路径198NSString *path = [[NSBundle mainBundle]pathForResource:@"app.plist"ofType:nil];199200//加载数组201NSArray *dictArray =[NSArray arrayWithContentsOfFile:path];202203//创建一个可变数组,来动态接收模型对象204NSMutableArray *array =[NSMutableArray array];205206//通过循环,将字典数组的字典取出,转成模型对象207for(NSDictionary *dictindictArray) {208KZAppModel *appModel =[KZAppModel appWithModelDict:dict];209[array addObject:appModel];210}211_apps =array;212}213return_apps;214/*吃唐僧肉的小悟空-转载请注明出处http://www.cnblogs.com/hukezhu/*/215}216217- (void)didReceiveMemoryWarning {218[super didReceiveMemoryWarning];219//Dispose of any resources that can be recreated.220}221222@end
xib文件加载的两种方式:
1//方法1:2NSArray *objs = [[NSBundle mainBundle] loadNibNamed:@"KZAppView"owner:nil options:nil];3//这个方法会创建xib中的所有对象,并且将对象按顺序放到objs数组中456//方法27//bundle参数可以为nil,默认就是main bundle8UINib *nib = [UINib nibWithNibName:@"KZAppView"bundle:[NSBundle mainBundle]];9NSArray *objs = [nib instantiateWithOwner:nil options:nil];
获取xib中的控件有两种方式:
1.通过绑定tag来实现
2.利用subviews[index];的特性实现
注意:两种方式都需要强制类型转换
总结:分析本文中的实现代码,在控制器中使用了xib进行赋值,当然在这里只有一个控制器,假设开发过程中有多个控制器,每个控制器都要使用这个xib,那么每个控制器都要使用这些赋值语句在各自的控制器中实现,假设以后要增加控件或者修改,则需要在每个控制器中都要修改,不利于扩展,所以我们考虑将xib进行封装,使用xib时直接调用即可,假设有修改时,直接修改xib封装的文件,对于调用者没有影响.如下图:
所以,下篇文章再次进行改进,将xib进行封装.