博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
iOS之Tableview重用原理、重用出现的错乱三种解决方法、tablevew优化
阅读量:4289 次
发布时间:2019-05-27

本文共 4133 字,大约阅读时间需要 13 分钟。

cell重用机制原理:

缓存池原理:

tabevieew优化:

1、imageNamed 与 imageWithContentsOfFile的区别: 

2、没有交互的时候用calayer不用uiview;

3、页面元素多的时候,减少autolayout布局,采用frame。

4、提前计算并缓存好高度(布局),因为heightForRowAtIndexPath:是调用最频繁的方法。

5、复杂界面可采用异步绘制。

6、在大量图片展示时,可以滑动时按需加载,不需要刷新所有cell;

7、尽量少用或不用透明图层,多个透明元素重叠显示可采用合并成一张图片显示。

8、在heightForRowAtIndexPath:中尽量不使用cellForRowAtIndexPath:

9、图片解码时,CALayer 被提交到 GPU 前,CGImage 中的数据才会得到解码,GPU执行,卡主线程。常见的做法是在后台线程先把图片绘制到 CGBitmapContext 中,然后从 Bitmap 直接创建图片。

10、CALayer 的 border、圆角、阴影、遮罩(mask)触发的离屏渲染,可开启CALayer.shouldRasterize ,转嫁到CPU上或是截图或者采用图片实现。

11、使用RunLoop和多线程在闲时处理一些繁重的计算工作。

 

 

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

{

    static NSString *CellIdentifier =@"Cell";

    // UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; //改为以下的方法

    UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];//根据indexPath准确地取出一行,而不是从cell重用队列中取出

    if (cell ==nil) {

        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];

    }

    //...其他代码

}

 

 

 

 

 

 

 

方法2通过为每个cell指定不同的重用标识符(reuseIdentifier)来解决。

重用机制是根据相同的标识符来重用cell的,标识符不同的cell不能彼此重用。于是我们将每个cell的标识符都设置为不同,就可以避免不同cell重用的问题了。

 

示例代码:

 

 

[plain]

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

{

    

    NSString *CellIdentifier = [NSString stringWithFormat:@"Cell%d%d", [indexPath section], [indexPath row]];//indexPath来唯一确定cell

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];//出列可重用的cell

    if (cell ==nil) {

        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];

    }

    //...其他代码

}

 

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

{

    

    NSString *CellIdentifier = [NSString stringWithFormat:@"Cell%d%d", [indexPath section], [indexPath row]];//indexPath来唯一确定cell

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];//出列可重用的cell

    if (cell ==nil) {

        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];

    }

    //...其他代码

}

 

方法3 删除重用cell的所有子视图

 

这个方法是通过删除重用的cell的所有子视图,从而得到一个没有特殊格式的cell,供其他cell重用。

 

示例代码:

 

 

[plain]

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

{

    static NSString *CellIdentifier =@"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];//出列可重用的cell

    if (cell ==nil) {

        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];

    }

    else

    {

        //删除cell的所有子视图

        while ([cell.contentView.subviews lastObject] !=nil)

        {

            [(UIView*)[cell.contentView.subviews lastObject] removeFromSuperview];

        }

    }

    //...其他代码

}

 

 

=======

 

 

问题本质:  

因为你要添加的子视图并不是在自定义的cell中实现的,而是根据系统给的UITableViewCell这个类创建的实例,每次进图入cellForRow方法都会创建一个cell,每次都要创建一个子视图添(button,label之类的)加进去,会给占用很大的内存,所以采用了复 用的方法,但是问题就来了,当cell超出界面,从队列中拿过来复用的时候,其中子视图的内容并没有消除,这样你会原来的基础上再创建一个子视图添加上去 遮住了原来的视图,一般视图都是透明的这样的话就变成了一层层的叠加.

 

 

解决方法:

  下面给出得是一个label添加到cell中的例子

将具体的视图实例,添加到cell的contentView中

注意:如何在父视图中标识某个子视图?

step1:在添加子视图时,指定tag值(大于0)

step2:为了找出这个子视图,通过调用父视图的 viewWithTag 方法,就可以找到指定的视图

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell1" ];

    if (cell==nil) {

        cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"Cell1"];

    }

    //把索引给系统  forIndexPath:indexPath为注册准备的,如果要自己创建的话,就把这个去掉

    // cell.detailTextLabel.text=@"detail.. ";

   // cell.imageView.image=[UIImage imageNamed:@"icon1.png"];

    

    //cell.textLabel.text=@"helo";

    //先按照tag值试着去Cell中找,是否有标签

    UILabel  *label=(UILabel*)[cell.contentView viewWithTag:1];

    if (label==nil) {//如果没找到再新建

        label=[[UILabel alloc]init];

       //为label设置tag值

        label.tag=1;

        label.textColor=[UIColor redColor];

        label.font=[UIFont italicSystemFontOfSize:40];

        label.frame=CGRectMake(0, 0, cell.bounds.size.width, 42);

        label.textAlignment=NSTextAlignmentCenter;

        [cell.contentView addSubview:label];

 

    }

     label.text=[NSString stringWithFormat:@"   %ld", indexPath.row];

        

    return cell;

}        

 

转载地址:http://vbmgi.baihongyu.com/

你可能感兴趣的文章
最简单的基于librtmp的示例:发布(FLV通过RTMP发布)
查看>>
Windows/Linux下引用jar包,并用javac/java编译运行
查看>>
HttpClient使用详解
查看>>
HttpClient详解(一)
查看>>
httpclient 请求http数据,json转map
查看>>
git 常用命令
查看>>
用递归方法建立二叉树
查看>>
用递归方法对二叉树进行先序、中序和后序遍历
查看>>
翻转二叉树
查看>>
逆序链表
查看>>
epoll 使用详解
查看>>
stl 中 set容器用法
查看>>
有序数组求交集
查看>>
文字常量区与栈
查看>>
非阻塞connect 编写方法
查看>>
epoll 边沿触发
查看>>
String类 默认生成的函数
查看>>
Linux 软连接与硬链接
查看>>
视音频数据处理入门:H.264视频码流解析
查看>>
视音频数据处理入门:AAC音频码流解析
查看>>