iOS开发经验技巧之UITableViewCell的重用
来源:互联网 发布:macbook air卸载软件 编辑:程序博客网 时间:2024/06/14 15:22
今天在公司修改bug的时候,想到了UITableViewCell的重用的具体实现,好久不用了,然而了解它的重要性,感觉还是总结一下为好。
新建了个single view的工程,在storyboard上拖了个tableview,用最基础的方法绑定了cell,并用了重用。
<span style="font-size:14px;">-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { //为表格行定义一个静态字符串作为标示 static NSString *cellID = @"cellId"; NSLog(@"hanghao:%ld",(long)indexPath.row); //从可重用的表格行的队列中取出一个表格行 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID]; if (cell == nil) { NSLog(@"重新创建对象"); switch (indexPath.row % 4) { case 0: //使用UITableViewCell创建普通单元格,使用自定义的LYCTableViewCell创建自定义单元格 cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellID]; break; case 1: cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID]; break; case 2: cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellID]; break; case 3: cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue2 reuseIdentifier:cellID]; break; default: break; } } //单元格设为圆角 cell.layer.cornerRadius = 12; cell.layer.masksToBounds = YES; //获取当前的行号 NSUInteger rowNo = indexPath.row; cell.textLabel.text = [books objectAtIndex:rowNo]; //为uitableviewcell左端设置图片 cell.imageView.image = [UIImage imageNamed:@"123.png"]; //设置左端高亮图片 cell.imageView.highlightedImage = [UIImage imageNamed:@"123_h.png"]; cell.detailTextLabel.text = [details objectAtIndex:rowNo]; return cell; }</span>
对于cell的重用,有单一类型的重用,以及多个自定义类型的cell的重用。
先说简单的情况,当我们的tableview种的cell为单一类型,而且cell的高度是一个统一的高度,即显示一个这样的列表:
例如上图,那么在 -(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
方法中,if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cID];
}
这几行代码将被执行11次,也就是创建11个指向不同地址的cell。
为什么是11次?因为当前window中显示了11个cell,虽然最后一个只显示了一半。(如果在iphone 6 plus中,创建的cell肯定大于 11个,因为屏幕比5s的大)
这是在静止时候创建的cell。
那么当我们滑动屏幕的时候,有会发生或者触发哪些操作呢?
上面的图中,为将tableview向上滑动了一点,出现了一个新的cell(android高级),这个时候,系统会在创建一个新的cell对象,此时的内存中会有12个cell的对象。
当我们继续向上滑动,当[C#高级编程]对应的那个cell消失在 tableview的可视区域 的时候,那个cell将被tableview放到他的重用列表中。
而新出现的cell将会重用重用列表中的那个cell,只是对cell中的文本重新赋值而已,
这样一直循环:当用户滚动tableview时,如果cell不可见,将被扔进可重用列表,在其他行即将显示在tableview中时,重用那个cell,重新复制,以达到节省内存的效果。
按照上面的例子,那么内存中最多会创建12个cell,即使你的datasource中有1000条数据,也还是12个cell对象在内存中,只是tableview替我们控制了显示隐藏时重用cell。
如果我们不在编程时使用重用机制,那么可想而知,创建1000个甚至10000个cell在内存中,是多么浪费。
上面讲了单一种类cell的现实,那么多种cell是怎么显示的呢,其实只要上面的思路清晰了,那么多种cell也是同样的道理。
<span style="font-size:12px;">#pragma mark - Table view data source - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { // Return the number of sections. return 4; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { // Return the number of rows in the section. NSLog(@"rowNumber"); if (section % 2 == 0) { return 1; } return 30; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *defaultCellID = @"default"; static NSString *firstCellID = @"first"; //注册可重用cell if (!_isRegistNib) { NSLog(@"registernib"); UINib *nib = [UINib nibWithNibName:@"CustomTableCellDefaultView" bundle:nil]; [tableView registerNib:nib forCellReuseIdentifier:defaultCellID]; UINib *nibFirst = [UINib nibWithNibName:@"HomeTableCellFirstView" bundle:nil]; [tableView registerNib:nibFirst forCellReuseIdentifier:firstCellID]; _isRegistNib = !_isRegistNib; } NSInteger sectionIndex = indexPath.section; if (sectionIndex % 2 == 0) { //如果是第一个区域,显示欢迎的cell HomeTableCellFirst *cell = (HomeTableCellFirst *)[tableView dequeueReusableCellWithIdentifier:firstCellID forIndexPath:indexPath]; NSLog(@"创建第一个cell"); NSLog(@"cell的地址是:%@",cell); NSLog(@"--------------------------------------"); return cell; } else if(sectionIndex % 2 == 1){ //如果是第二个区域,显示普通的cell CustomTableCellDefault *cell = (CustomTableCellDefault *)[tableView dequeueReusableCellWithIdentifier:defaultCellID forIndexPath:indexPath]; NSLog(@"创建普通的cell"); NSLog(@"cell的地址是:%@",cell); NSLog(@"--------------------------------------"); cell.lblStoreName.text = [NSString stringWithFormat:@"店家%ld",(indexPath.row+1)]; return cell; } else{return nil;} }-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { if (indexPath.section % 2 == 0) { return 150;</span>
<span style="font-size:12px;">} return 80; } -(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { return 10; }</span>
上面的tableview实在ib中拖进去的,style时group
在代码中设置了section的数量是4,在- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
方法中,使用 registerNib:forCellReuseIdentifier 方法注册了两种自定义的cell,并且会打印cell的地址及其他信息,先来看下运行效果
刚打开view的时候,tableview一共加载了[cell1]一个,[cell2] 7个。
当我们继续向上滚动的时候,因为当前[cell2]的数量并不能充满整个window,所以还会继续创建cell2的对象,与此同时,唯一的一个cell1消失在window的时候,被tableview扔进了重用列表。
通过上面的图,看到nslog打印出来的cell指向的地址,很清楚,我们创建了7个不同的[cell2]对象
当继续滚动的时候,会继续打印出和上面地址不重复的[cell2],大家可以自己试试,我就不上图了
因为我让第三个section又显示了[cell1],所以继续向下滚动,当它出现时,控制台打印的cell的地址是0x7fbc2176c620,和第一个cell是同一个对象,因为使用了重用列表中的那个[cell1]的对象。
通过上面的实验,可以总结下面的结论:
使用重用机制后:
1、tableview至少会创建 可视区域高度 / cell高度 个 cell对象,因为当第一个cell隐藏了一半时,意味着要还要创建一个新的cell
2、创建了足够多的cell后,再显示cell就会使用可重用队列中的cell
- iOS开发经验技巧之UITableViewCell的重用
- iOS之UITableViewCell的重用机制
- iOS-UITableviewCell的重用机制
- iOS-UITableviewCell的重用机制
- iOS-UITableviewCell的重用机制
- iOS-UITableviewCell的重用机制
- iOS-UITableviewCell的重用机制
- iOS-UITableviewCell的重用机制
- iOS-UITableviewCell的重用机制
- iOS UITableviewCell的重用机制
- iOS-UITableviewCell的重用机制
- iOS-UITableviewCell的重用机制
- iOS-UITableviewCell的重用机制
- ios-提升之【2】-UITableViewCell的重用机制
- iOS开发~UITableViewCell重用机制总结
- IOS学习-UITableViewCell的重用机制原理
- [IOS]轻松理解UITableViewCell的重用机制
- iOS中UITableViewCell的重用问题解决方案
- windows 安装环回适配器
- Android aapt介绍
- 我对JavaScript原型的理解
- MFC之MessageBox用法
- ios学习(四) GCDiscreetNotificationView提示视图
- iOS开发经验技巧之UITableViewCell的重用
- leetcode_Best Time to Buy and Sell Stock III
- 2015年大一下第8周项目4-点类派生直线类
- result
- ubuntu创建wifi热点(手机可识别)
- .HTM与.HTML的区别
- cookie和session杂记
- Harry Potter and the Chamber of Secrets
- winform配置文件的简单使用