UITableView是app开发中常用到的控件,功能很强大,常用于数据的显示。在学习UITableView使用之前,我们先简单了解一下:

1、UITableView的重用机制

UITableView最核心的思想就是UITableViewCell的重用机制,对于一个UITableView而言,可能需要显示成百上千个Cell,如果每个cell都单独创建的话,会消耗很大的内存,为了避免这种情况,重用机制就诞生了。

UITableView的重用机制的实现关键在于下面这个的函数:UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];首先,我们要清楚这一点,这个函数是做什么的,它的文档说明如下:
returns a reusable table-view cell object located by its identifier。它返回的是一个受identifier管理定位的可重用的tableViewCell,这里重点就在于“可重用”这3个字上。

假设某个UITableView有100个数据需要显示,即需要100个Cell,然而屏幕中最多只能一次性显示10个Cell,那么有一个办法可以不用创建100cell,而只需要创建(10+1)个;

滑动 tableview 的时候,刚离开视图的 cell 会被放到复用池 中,等下一个 cell需要 显示时,会先看复用池中有没有 cell 如果有的时候 ,就从复用池中拿出来cell ,没有的话就重新创建cell 。如下代码:

    static NSString *reuseIndentifier = @"UITableViewCell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseIndentifier];
    if (!cell) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseIndentifier];
    }

创建UITableViewCellStyleDefault类型的cell,并将其标识为identifier;这样一个cell就创建完成了。当需要第2个cell的时候,同样也是先从重用队列里去取,发现还是没有,那么继续创建。可想而知,刚进到这个页面的时候需要创建10个cell,且他们的标识符都是identifier。

当我们下拉tableView,我们知道会出现第11个cell。这个时候还是先从重用队列里去取,发现没有,继续创建第11个cell并返回,这个时候,当第11个cell完全显示出来,第1个cell也刚好完全消失,这样第一个cell(标记为cell1)被放进重用队列了”。

再继续下拉,就要出现第12个cell了,同样的,还是要先调用dequeueReusableCellWithIdentifier:方法,从重用队列中寻找cell,这个时候队列中有cell1,就会被取出来,这时候if(!cell)条件不成立,也就不会创建新的cell了,这个cell被返回作为第12个cell,当第12个cell完全显示,第2个cell就完全消失进入重用队列了。可想而知,在13、14...也是如此,所以说,尽管需要100个cell,实际上只需创建11个cell,这就是重用机制。

2、列表的重复混乱问题

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

    static NSString *reuseIndentifier = @"UITableViewCell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseIndentifier];
    if (!cell) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseIndentifier];
    }
    UILabel *label = [[UILabel alloc]initWithFrame:(CGRect){,,,}];
    label.text = [NSString stringWithFormat:@"第%d行",(int)indexPath.row];
    [cell addSubview:label];

    return cell;

}

我们在每个cell中添加了一个label,运行,下拉,我们会发现如下现象:

这是因为每次新出现的cell都是之前用过的,再对它添加label就是在原来基础上又添加了一次,所以会出现上图所示列表混乱的现象。怎么解决这种现象呢?

方法一:在建立新的label之前,把之前创建label移除

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

    static NSString *reuseIndentifier = @"UITableViewCell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseIndentifier];
    if (!cell) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseIndentifier];
    }

    //移除所有子视图
    [cell.subviews enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        UIView *view = (UIView*)obj;
        [view removeFromSuperview];
    }];

    //添加新视图
    UILabel *label = [[UILabel alloc]initWithFrame:(CGRect){,,,}];
    label.text = [NSString stringWithFormat:@"第%d行",(int)indexPath.row];
    [cell addSubview:label];

    return cell;

}

方法二:这种方法放弃了重用机制,每次根据indexPath获取对应的cell返回。

将方法:  UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseIndentifier];

用方法:  UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]; 替换。

iOS基础篇(十三)——UITableView(一)重用机制的更多相关文章

  1. ios基础篇(十四)——UITableView(二)属性及基本用法

    上一篇说了UITableView的重用机制,让我们对UITableView有了简单了解,下面说说UITableView的属性及常见方法. 一.属性 1.frame:设置控件的尺寸和大小 2.backg ...

  2. ios基础篇(二十八)—— UITableView的上拉加载

    本文主要展示一个demo实现UITableView的上拉加载数据: 先看看效果图: 接着上拉,加载更多数据: 主要实现的效果是在我们上拉结束拖拽之后,开始加载数据,数据加载的过程中有滚动轮提示用户正在 ...

  3. ios基础篇(二十三)—— 定时器NSTimer与图片的自动切换

    一.NSTimer NSTimer是一个能在从现在开始到后面的某一个时刻或者周期性的执行我们指定的方法的对象.可以按照一定的时间间隔,将制定的信息发送给目标对象.并更新某个对象的行为.你可以选择在未来 ...

  4. ios基础篇(二十六)—— UITableViewCell的分组索引与标记

    一.表视图的索引目录 首先要创建一个TableView,之前有说过,这里就不详细说了(参考前面第十四篇). 直接贴代码吧, #import "ViewController.h" @ ...

  5. ios基础篇(十六)——UIWebView的基本使用

    UIWebView是内置的浏览器控件,可以用它来浏览网页.打开文档等.UIWebView是一个混合体,具体的功能控件内置的,实现一些基本的功能.UIWebView可以查看Html网页,pdf文件,do ...

  6. J2EE基础篇——十三个规范

    背景: 1.企业级应用框架的需求,在很多企业级应用中.比如数据库连接.邮件服务.事务处理等都是一些通用企业需求模块,这些模块假设每次在开发中都由开发者来完毕的话,将会造成开发周期长和代码可靠性差等问题 ...

  7. ios基础篇(十八)——Delegate 、NSNotification 和 KVO用法及其区别

    一.Delegate Delegate本质是一种程序设计模型,iOS中使用Delegate主要用于两个页面之间的数据传递.iphone中常用@protocol和delegate的机制来实现接口的功能. ...

  8. ios基础篇(二十九)—— 多线程(Thread、Cocoa operations和GCD)

    一.进程与线程 1.进程 进程是指在系统中正在运行的一个应用程序,每个进程之间是独立的,每个进程均运行在其专用且受保护的内存空间内: 如果我们把CPU比作一个工厂,那么进程就好比工厂的车间,一个工厂有 ...

  9. ios基础篇(二十七)—— Json解析

    一.什么是Json JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.它基于ECMAScript的一个子集. JSON采用完全独立于语言的文本格式,但是也使 ...

随机推荐

  1. 在VisualStadio2015上使用EF6.0建立MySql数据库

    1.新建工程 2.建立类的文件夹DAL 3.建立相关类 [Student类] using System;using System.Collections.Generic;using System.Li ...

  2. selenium常用的js总结

    1. 对input执行输入 直接设置value属性, 此方法主要应对输入框自动补全以及readonly属性的element,sendkeys不稳定 比如: //inputbox is a WebEle ...

  3. project euler 开坑

    pe76: 要把100写成至少2个数的和的形式,有多少种方案数 整数拆分 f(i,j)表示把i拆分成不超过j的数的和的方案数 f(i,j) = f(i-j,j) + f(i,j-1)  j <= ...

  4. CPU供电维修

  5. ERP开发分享 1 数据库表设计

    这是我的ERP设计经验分享系列,今天讲的是数据库的表设计(1),主要阐述: 1.单字段的主键:2.使用int32作为主键类型:3.使用版本字段处理乐观锁定:4.生效字段标明是否允许“被使用”:5.锁定 ...

  6. 模拟一下goldengate中断后,重新同步操作

    模拟一下goldengata中断后,重新同步操作:     1.关掉源端抽取进程 GGSCI (20081122-2105) 15> info all Program     Status    ...

  7. Android 解析JSONObject以及JSONArray对比

    在Android客户端与服务器交互的过程中,客户端一般采用json解析服务器的返回数据.此时有两种数据格式.但其根本都是字符串或字符串数组! 1.JSONObject 下面是PHP端代码: <? ...

  8. SQL中的模糊查询

    写个标题先.先来一篇大神的文章:http://www.cnblogs.com/GT_Andy/archive/2009/12/25/1921914.html 练习代码如下: 1.百分号:%   表示任 ...

  9. 3143: [Hnoi2013]游走 - BZOJ

    Description 一个无向连通图,顶点从1编号到N,边从1编号到M. 小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概率随机选 择当前顶点的某条边,沿着这条边走到下一个顶点, ...

  10. WCF入门(十一)---WCF安全

    一个强大的WCF服务安全系统,拥有两种安全模式或级别预期的客户端可以访问的服务.这是常见的分布式事务的安全威胁正在放缓,在很大程度上由WCF决定. 关键的安全功能 WCF服务有四个主要的安全功能,如下 ...