1. 图片浏览器
问题:
- 需求:是做一个按钮控制图片和文本变化的功能.
- 要求:代码复用性,封装性:使监听点击的方法中:只要结果.实现过程在另外定义的方法中.
思路:
- storyboard中简单搭建布局.之后连接需要的属性和方法.(IB)
图片数据与文本数据等一般是plist文件直接提供,所以需要加载.出于能效考虑,在出现需要使用数据时才加载,称为懒加载–改写存储数据的集合(实例变量)的get方法.
例:
-(NSArray *)imageData{
//先判断是否为空
if(_imageData==nil){
/*******获取plist数据******/
NSString *path = [[NSBundle mainBundle] pathForResource@"plist文件名" ofType@"plist"]; //[NSBundle mainBundle]表示获取主安装包的位置,从此位置中搜索plist文件.
//加载到程序中
_imageData=[NSArray arrayWithContentsOfFile:path];
}
return _imageData;
}
如果图片数据不是plist文件而是单独的.那么拖入开发文件后,使用UIImage方法从图片名获取.不过这是添加到集合中需要使用循环来addObject.
- 之后把具体改变过程封装,调用.
- 小细节1:需要一个小标来记录对应的字典数据,且控制按钮是否禁用. 注意下顺序.
- 小细节2:UI控件使用weak和非UI控件使用strong关键字.原因
在于:我们的UIViewController系统自动生成了一个View,是强指向,而使用的UI控件都是属于此UIView的子类,所以已经被被强指向了,不要要再strong.
2.UIImageView的序列帧动画.
原理:一连贯的图片连续播放.
特点:
- 1)整个动画以数组形式保存在内存,动画所需图片越大,占内存越大.
- 2)假如需要流畅播放,就不能清空图片,否则重新加载会稍慢,但如果需要节约内存,又需要每次清空图片.(局限)
思路:
- 简单UI搭建.布局.连接属性方法.
加载图片赋值到UIImageView自带的动画执行数组中
- 2.1预封装方法中创建可变临时数组,用来存储临时图片
- 2.2循环生成图片名->根据图片名生成图片对象->add到临时数组中
- 2.3把临时数组赋给动画数组.
设置动画属性次数,时间.执行动画.
- 当多个动画组时,需要进行抽取代码封装,延迟释放数组动画内存
- 细节:1/如果动画正在执行,加入判断不使其中断. 2/如果图片在主安装包的Assets.car文件中,我们则可以通过imageName:方法来获取其内部的图片.但是无法使用imageWithContentsOfFile:来获取其内部的图片. (asset 资产,资源)//使用Assets.car文件会产生缓存.直接通过全路径得到的主安装包内的图片,不会产生程序在运行中缓存的问题
实例:因为资源不是plist文件格式,所以只能循环获取.应为缓存,所以多一步路径获取.
-(void)performAnimationWithImageName:(NSString *)name imageCout:(int) count{
//不中断动画
if(self.tomCatImageView.isAnimating) return;
//1,创建临时可变数组.
NSMutableArray * array=[NSMutabelArray array];
//加载流程:
for(int i=0;i<count;i++){
//获取图片名.
NNString *str=[NSString stringWithFormat@"%@_%02d",name,count];
//由图片名获取地址,由路径加载图片对象,
NSString *path=[NSBundle mainBundle] pathForResource:str ofYType:nil];
UIImage *image=[UIImage imageWithContentsOfFile:path];
//add到可变数组
[array addObject:image];
//赋值给动画数组;
self.tomCatImageView.animationImages = imageArray;
// 6. 设置动画重复次数, 精确动画播放的时间, 并开始动画
// 重复次数
self.tomCatImageView.animationRepeatCount = 1;
// 动画播放的时间
self.tomCatImageView.animationDuration = self.tomCatImageView.animationImages.count*0.05;
// 开始动画
[self.tomCatImageView startAnimating];
// 7. 延迟释放 self.tomCatImageView 的 animationImages数组 (最后的图片缓存)
[self.tomCatImageView performSelector:@selector(setAnimationImages:) withObject:nil afterDelay:self.tomCatImageView.animationDuration + 1.0f];
}
3.应用管理实例.
3.1 九宫格实现.
纯代码实现:几点注意
- UIButton比较特殊,它由4总状态,有些属性必须用 setXXX来设置.(文本,文本颜色,背景图片等)不能用点语法.
- 纯代码创建的控件如何获取它的值内(作用域结束会被释放),很简单多一个指针指向,怎样的指针呢.定义同名的实例变量(有_区分),使之指向代码创建的控件—-类似IBOutlet的连线.可看成手动连线.同样的道理,加载来的数据也需要定义一个实例变量来接收,指向.连线.
思路:
思想-对于多组行列顺序排列的同类控件组, 创建一个子view,用来打包这样一组控件组. 之后行列数索引来单独设置属性.(for循环的计数器为依据.)
步骤:
- 确定每个app的宽和高,以及每行个数count.
- 计算marginX,据此 marginY,设置 marginTop值
- 计算每个app所在的行索引 i%count 、列索引 i/count .
- 根据当前app的行索引和列索引计算appX和appY
代码:
CGFloat appW = 75;
CGFloat appH = 90;
// 第一行的View距离顶部的距离
CGFloat marginTop = 30;
// 每一行上应用的个数
int columns = 3;
// marginX = (屏幕的宽度 - appW * columns) / (cllumns + 1)
CGFloat marginX = (self.view.frame.size.width - appW * columns) / (columns + 1);
CGFloat marginY = marginX; //
for (int i = 0; i <self.apps.count; i++) {
// 获取当前循环遍历的数据对象
NSDictionary *appDict = self.apps[i];
// 创建UIView显示到屏幕上
UIView *appView = [[UIView alloc] init];
// 计算每一个格子的行索引
int row = i / columns;
// 计算当前格子所在列的索引
int col = i % columns;
// appX = marginX + 当前appView所在的列索引 * (marginX + appW);
// appY = marginTop + row * (appH + marginY)
// 设置appView的frame
CGFloat appX = marginX + col * (appW + marginX);
CGFloat appY = marginTop + row * (appH + marginY);
appView.frame = CGRectMake(appX, appY, appW, appH);
3.2 字典转模型.
模型就是类对象,每个字典对应了一个对象,字典的key对应模型的实例变量. 字典的值赋给模型实例变量.这就是字典转模型.
思路:
- 需要一一对应的转换,所以需要循环遍历,
- 因为一一对应的转换,所以需要可变数组来接受转换后的一个个模型对象.
- 把懒加载结合起来,就是在加载字典数据完成之后,for遍历一一转换,存到数组,再数组整体记录到同名的self.实例变量中.(=)
- 封装思想:把一一转换过程封装起来,编写模型的快速创建初始化方法来调用解决.
代码实现:
//模型里面实现方法我就不写了.直接上懒加载的.
-(NSArray *)modeArray{//
if(_modeArray == nil){
//忘记新建临时可变数组接收模型对象了 ,补上
NSMutableArray *modeArray=[NSMutableArray array];
//先处理字典过程.获取绝对路径
NSString *path=[[NSBundle mainBundle] pathForResourse:@"plist文件名" ofType nil];
//路径文件生成字典数组..........
NSArray *dictArray=[NSArray arrayWithContentsOfFile:path];
//快速遍历:
for(NSDictionary *dict in dictArray){
//方法 1.创建模型,准备接受字典数据.
//Heap *modeApp=[HMapp alloc]init];
//用实例变量接收存储
//modeApp.name=dict[@"name"];
//modeApp.icon=dict[@"icon"];
//方法 2.调用模型里写的快速创建方法.
HMapp *modeApp=[HMapp alloc]initWithDict:dict];
//加到临时数组中
[modeArray addObject:modeApp]
}
//记录数据
self.modeArray=modeArray;//名称一致,易于识别.
}
return self.modeArray;
}
3.3 封装.
MVC编程思想,编写自己的标准方法.方便大家使用.简单造轮子.
- 理解:MVC即,数据-控制器-视图的关系. 视图用来显示数据.但是我们不应该把访问数据的权限交给视图.我们操作控制器,进行程序业务逻辑控制,保障在正确的时间顺序上把正确的数据传给正确的视图.
- MVC型似荷花结构. 主体根是控制器. 叶子是xib的view和对应的类. 根须是存储的数据模型.
根须从土地(数据文件)中 加载数据.传输到 根控制器中. 分配到不同的view类中显示出来. 所有的叶子添加到最后的花就就衬托出了最后结果.
应用:
xib文件加载:很多视窗要作为个体单独设置子控件.之后利用控制器传输的数据进行属性设置.在添加到主视图上.—封装思想,复用性,耦合性等原因.减轻了控制器大量创建控件的压力
MVC的步骤与思路:
- 新建xib,拖控件进行UI布局.
- 加载xib到对应的类中此类也先定义模型实例变量由于接收数据,并进行控件属性和功能的设置.需要的数据,控制器调用时会传输.
- 控制器中先定义模型类型的数组,懒加载数据文件到模型类,add到数组中.即控制器获取数据
- 控制器获取xib视图类.调用其创建方法 传给数据.即等到了..
- 代码太多,详情请看附件;
PS.注意:
- 使用等待执行语句时(动画).在等待执行某句代码的时候,系统不是真的在休息,而是执行后面代码,在等待时间结束时再执行此句代码;
- 注意 : 一定要将xib中的类名修改为自定义的类,这样才能在自定义的类中进行连线.
- ?数据模型类中是重写set方法?,快速创建需字典参数(字典转模型方法),实例变量名要和字典Key名一样.(方便使用KVC)
- xib对应类是重写set方法来设置控件必要属性.定义有模型类型的实例变量,快速创建方法含有加载xib文件代码: loadNib.
- 控制器懒加载是重写get方法.注意一点.重写方法一定不能有错.注意冒号和大写.
- 有时要关闭自动布局才能显示控件的改变效果.