iOS UITableViewCell重用机制理解之初级剑侠篇(欢迎提建议和分享遇到的问题)

本文主要是介绍iOS UITableViewCell重用机制理解之初级剑侠篇(欢迎提建议和分享遇到的问题),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

@dequeueResableCellWithIdentifier方法:这个单词翻译一下就是“出列的可重用的cell”

       iphone重用机制是苹果为了实现大量数据显示而采用的一种节省内存的机制,比如在UITableView和ScrollView 等地方。为什么要“可重用”?对于我们的项目来说,内存控制是必不可少的,如果一个tableview有几百个cell,这个内存消耗是很大的,而且有些cell里面都有image之类的很占内存的资源存在的话,那这样很容易出现memory warning甚至crash掉,这不是我们想要看到的。对
此,tableview实现了它自己的管理方法dequeueReusableCellWithIdentifier(ps:我们在某些项目中scrollview来显示很多张image,在scrollview滑动中也要这样处理,来避免内存的过度消耗,只不过tableview它已经实现了这个方法,而不用我们自己去写)。
       reuse机制:当cell需要显示的时候,从queue里面找,找到了,设置一下内容,显示出来滚动界面当有cell被移出屏幕时,把这个cell丢到queue里面。显示新的cell时,如果有“相同类型”(identifier)的cell,就从队列拿一个出来,设置数据,显示出来。至于queue里面会有多少cell,这个会自动控制。 其实也就是在"屏幕显示的cell数量"是有限的。当屏幕滚动时候,就会调用方法获取新的cell,而老的cell在屏幕外面就不显示了。

//对table view的数据进行绑定,即填充cell,自动调用n次
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {  
      
    static NSString *CellIdentifer = @"Cell";     //  0  
      

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:Cell];      //   1  


    if (cell == nil) {  

        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault  reuseIdentifier:CellIdentifer] ;    //  2  
    }  
      
    // Config your cell  
     cell.textlabel.text = @"XXX";    //  3  
      
    return cell;

    }

@可以这样理解,cell有一个地方(假设称为队列),专门存放那些生成过的,但是后来由于滚动tableView而隐藏起来的cell,而代码中语句1就是从队列中根据标示符取出一个暂时不用的cell,只有cell为nil,也就是队列中没有旧的cell的时候,才会执行语句2,生成一个新的cell。如果有旧的,就不用执行语句2了,这样节省资源,算作一种重用吧。在tableView初始化的时候队列中肯定没有cell的,所以每个cell生成的时候都会执行一遍2,当屏幕显示满了,向上滚动显示下一行时,就会把第一行隐藏,放到那个队列中,然后新增加的一行执行语句1的时候,结果就不是nil了,然后,就跳过语句2了,这样就节约资源了。

@当然,上面这样对于使用系统提供的cell格式是没有什么问题,但是如果自己在cell上添加一些控件时,比如一个label,有时就会出现问题。尤其是各个cell的label的文字不相同时。首先这个添加的过程一定要在语句2之后,这样才是一次添加,如果放在语句3之后,那么由于cell的重用可能旧的上面已经有label了,你再添加一个,造成多次添加。其次label的文本值必须保证每次都要重新设置,也就是在语句3之后设置,这样才能保证每次必须执行。如果放在语句2后面,那么当使用旧的cell时,仍会保留旧的label文字,这是不对的。所以是在2后添加,在3后设置,可以在2添加的时候设一个tag值,这样可以在3处通过tag值获取控件设置。


@插句话:如果用自己做的Cell的话,可以在初始化的时候设置,在赋值的时候设置数据,跟上面的意思一样


@关于语句0,如果每个cell的结构完全相同,那没问题,就用这一个标识符,但是如果各个cell结构不完全相同,有的有textfield,有的有button,有的有switch,那就不能互相重用了,只能每行用不同的标识符了,可以方便的利用(NSString *CellIdentifier = [NSString stringWithFormat:@"%@%U_%U",@"Cell",indexPath.section,indexPath.row];),保证不会重复,多组的再加上组号。那这还有必要用语句2吗?还是需要的,因为当自己滚动隐藏,下次再显示出来的时候,还是可以重用的。标识符完全可以每次用一个新的,但为了最大限度的重用性,节省资源,才想了这么多办法。

@总之,注意添加控件的位置,注意设置控件的位置,注意cell标识符。



uitableviewcell出错及解决办法,大家有更好的 可以提供分享啊


UITableView继承自UIScrollview,是苹果为我们封装好的一个基于scroll的控件。上面主要是一个个的UITableViewCell,可以让UITableViewCell响应一些点击事件,也可以在UITableViewCell中加入UITextField或者UITextView等子视图,使得可以在cell上进行文字编辑。


UITableView中的cell可以有很多,一般会通过重用cell来达到节省内存的目的:通过为每个cell指定一个重用标识符(reuseIdentifier),即指定了单元格的种类,当cell滚出屏幕时,会将滚出屏幕的单元格放入重用的queue中,当某个未在屏幕上的单元格要显示的时候,就从这个queue中取出单元格进行重用。

但对于多变的自定义cell,有时这种重用机制会出错。比如,当一个cell含有一个UITextField的子类并被放在重用queue中以待重用,这时如果一个未包含任何子视图的cell要显示在屏幕上,就会取出并使用这个重用的cell显示在无任何子视图的cell中,这时候就会出错。

解决方法:

方法1 将获得cell的方法从- (UITableViewCell*)dequeueReusableCellWithIdentifier:(NSString*)identifier 换为-(UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath *)indexPath

重用机制调用的就是dequeueReusableCellWithIdentifier这个方法,方法的意思就是“出列可重用的cell”,因而只要将它换为cellForRowAtIndexPath(只从要更新的cell的那一行取出cell),就可以不使用重用机制,因而问题就可以得到解决,虽然可能会浪费一些空间。

示例代码:


[plain]
- (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]; 
    } 
     //...其他代码                               

- (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]; 
        } 
    } 
    //...其他代码 


这篇关于iOS UITableViewCell重用机制理解之初级剑侠篇(欢迎提建议和分享遇到的问题)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1088522

相关文章

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

好题——hdu2522(小数问题:求1/n的第一个循环节)

好喜欢这题,第一次做小数问题,一开始真心没思路,然后参考了网上的一些资料。 知识点***********************************无限不循环小数即无理数,不能写作两整数之比*****************************(一开始没想到,小学没学好) 此题1/n肯定是一个有限循环小数,了解这些后就能做此题了。 按照除法的机制,用一个函数表示出来就可以了,代码如下

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

认识、理解、分类——acm之搜索

普通搜索方法有两种:1、广度优先搜索;2、深度优先搜索; 更多搜索方法: 3、双向广度优先搜索; 4、启发式搜索(包括A*算法等); 搜索通常会用到的知识点:状态压缩(位压缩,利用hash思想压缩)。

【专题】2024飞行汽车技术全景报告合集PDF分享(附原数据表)

原文链接: https://tecdat.cn/?p=37628 6月16日,小鹏汇天旅航者X2在北京大兴国际机场临空经济区完成首飞,这也是小鹏汇天的产品在京津冀地区进行的首次飞行。小鹏汇天方面还表示,公司准备量产,并计划今年四季度开启预售小鹏汇天分体式飞行汽车,探索分体式飞行汽车城际通勤。阅读原文,获取专题报告合集全文,解锁文末271份飞行汽车相关行业研究报告。 据悉,业内人士对飞行汽车行业

安卓链接正常显示,ios#符被转义%23导致链接访问404

原因分析: url中含有特殊字符 中文未编码 都有可能导致URL转换失败,所以需要对url编码处理  如下: guard let allowUrl = webUrl.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else {return} 后面发现当url中有#号时,会被误伤转义为%23,导致链接无法访问

购买磨轮平衡机时应该注意什么问题和技巧

在购买磨轮平衡机时,您应该注意以下几个关键点: 平衡精度 平衡精度是衡量平衡机性能的核心指标,直接影响到不平衡量的检测与校准的准确性,从而决定磨轮的振动和噪声水平。高精度的平衡机能显著减少振动和噪声,提高磨削加工的精度。 转速范围 宽广的转速范围意味着平衡机能够处理更多种类的磨轮,适应不同的工作条件和规格要求。 振动监测能力 振动监测能力是评估平衡机性能的重要因素。通过传感器实时监

缓存雪崩问题

缓存雪崩是缓存中大量key失效后当高并发到来时导致大量请求到数据库,瞬间耗尽数据库资源,导致数据库无法使用。 解决方案: 1、使用锁进行控制 2、对同一类型信息的key设置不同的过期时间 3、缓存预热 1. 什么是缓存雪崩 缓存雪崩是指在短时间内,大量缓存数据同时失效,导致所有请求直接涌向数据库,瞬间增加数据库的负载压力,可能导致数据库性能下降甚至崩溃。这种情况往往发生在缓存中大量 k

【生成模型系列(初级)】嵌入(Embedding)方程——自然语言处理的数学灵魂【通俗理解】

【通俗理解】嵌入(Embedding)方程——自然语言处理的数学灵魂 关键词提炼 #嵌入方程 #自然语言处理 #词向量 #机器学习 #神经网络 #向量空间模型 #Siri #Google翻译 #AlexNet 第一节:嵌入方程的类比与核心概念【尽可能通俗】 嵌入方程可以被看作是自然语言处理中的“翻译机”,它将文本中的单词或短语转换成计算机能够理解的数学形式,即向量。 正如翻译机将一种语言