图片浏览器和九宫格

1. 图片浏览器

问题:

  • 需求:是做一个按钮控制图片和文本变化的功能.
  • 要求:代码复用性,封装性:使监听点击的方法中:只要结果.实现过程在另外定义的方法中.

思路:

  1. storyboard中简单搭建布局.之后连接需要的属性和方法.(IB)
  2. 图片数据与文本数据等一般是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)假如需要流畅播放,就不能清空图片,否则重新加载会稍慢,但如果需要节约内存,又需要每次清空图片.(局限)

思路:

  1. 简单UI搭建.布局.连接属性方法.
  2. 加载图片赋值到UIImageView自带的动画执行数组中

    • 2.1预封装方法中创建可变临时数组,用来存储临时图片
    • 2.2循环生成图片名->根据图片名生成图片对象->add到临时数组中
    • 2.3把临时数组赋给动画数组.
  3. 设置动画属性次数,时间.执行动画.

  4. 当多个动画组时,需要进行抽取代码封装,延迟释放数组动画内存
  5. 细节: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 九宫格实现.

纯代码实现:几点注意

  1. UIButton比较特殊,它由4总状态,有些属性必须用 setXXX来设置.(文本,文本颜色,背景图片等)不能用点语法.
  2. 纯代码创建的控件如何获取它的值内(作用域结束会被释放),很简单多一个指针指向,怎样的指针呢.定义同名的实例变量(有_区分),使之指向代码创建的控件—-类似IBOutlet的连线.可看成手动连线.同样的道理,加载来的数据也需要定义一个实例变量来接收,指向.连线.

思路:
思想-对于多组行列顺序排列的同类控件组, 创建一个子view,用来打包这样一组控件组. 之后行列数索引来单独设置属性.(for循环的计数器为依据.)
步骤:

  1. 确定每个app的宽和高,以及每行个数count.
  2. 计算marginX,据此 marginY,设置 marginTop值
  3. 计算每个app所在的行索引 i%count 、列索引 i/count .
  4. 根据当前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对应模型的实例变量. 字典的值赋给模型实例变量.这就是字典转模型.

思路:

  1. 需要一一对应的转换,所以需要循环遍历,
  2. 因为一一对应的转换,所以需要可变数组来接受转换后的一个个模型对象.
  3. 把懒加载结合起来,就是在加载字典数据完成之后,for遍历一一转换,存到数组,再数组整体记录到同名的self.实例变量中.(=)
  4. 封装思想:把一一转换过程封装起来,编写模型的快速创建初始化方法来调用解决.

代码实现:

//模型里面实现方法我就不写了.直接上懒加载的.
-(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的步骤与思路:

  1. 新建xib,拖控件进行UI布局.
  2. 加载xib到对应的类中此类也先定义模型实例变量由于接收数据,并进行控件属性和功能的设置.需要的数据,控制器调用时会传输.
  3. 控制器中先定义模型类型的数组,懒加载数据文件到模型类,add到数组中.即控制器获取数据
  4. 控制器获取xib视图类.调用其创建方法 传给数据.即等到了..
  5. 代码太多,详情请看附件;

PS.注意:

  1. 使用等待执行语句时(动画).在等待执行某句代码的时候,系统不是真的在休息,而是执行后面代码,在等待时间结束时再执行此句代码;
  2. 注意 : 一定要将xib中的类名修改为自定义的类,这样才能在自定义的类中进行连线.
  3. ?数据模型类中是重写set方法?,快速创建需字典参数(字典转模型方法),实例变量名要和字典Key名一样.(方便使用KVC)
  4. xib对应类是重写set方法来设置控件必要属性.定义有模型类型的实例变量,快速创建方法含有加载xib文件代码: loadNib.
  5. 控制器懒加载是重写get方法.注意一点.重写方法一定不能有错.注意冒号和大写.
  6. 有时要关闭自动布局才能显示控件的改变效果.
    原文作者:九宫格问题
    原文地址: https://blog.csdn.net/csdnhaoren13/article/details/50739736
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞