UITableView 以及 UITableViewCell 的重用机制

直接上代码:

//
//  RootViewController.m
//
//

#import "RootViewController.h"
#import "DetailViewController.h"

/*
    TableView 作为一个空表,自身并不确定项目中需要展示的行数,显示的内容以及单元格的样式,所以需要通过代理来获取;
    TableView 对应的试图控制器需要遵守 UITableViewDataSource 协议,并实现两个必须实现的协议方法
    1、每一个分区需要展示多少行(通航协议方法返回值提供给 TableView )
    2、指定分区指定行所需要的单元格对象(通过协议方法返回值提供给 TableView ) TableView 真正展示数据的视图为其所管理的单元格,所以代理对象在协议方法中创建单元格的同时需要为单元格提供数据。
 */
@interface RootViewController ()<UITableViewDataSource, UITableViewDelegate>

@property (nonatomic, retain) NSArray *titles; //保存分区区头标题的数组

@end

@implementation RootViewController

- (void)dealloc {
    [_titles release];
    [super dealloc];
}

- (NSArray *)titles {
    if (!_titles) {
        self.titles = @[@"A", @"B", @"C", @"D", @"E", @"F"];
    }
    return _titles;
}

- (void)viewDidLoad {
    [super viewDidLoad];

    //创建 tableView 并指定样式
    UITableView *tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];

    //设置分割线的样式
    tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
    //设置分割线的颜色
    tableView.separatorColor = [UIColor blueColor];
    //设置分割线的内边距,分别为上,左,下,右
    tableView.separatorInset = UIEdgeInsetsMake(0, 10, 0, 10);
    //设置行高
    tableView.rowHeight = 50;

    //为 tableView 指定数据源代理。
    tableView.dataSource = self;
    //为 tableView 指定代理对象,做外观控制。
    tableView.delegate = self;

    [self.view addSubview:tableView];
    [tableView release];

}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

//这个代理方法先执行,只有先确定了行数才能为每个单元格添加内容。
- (NSInteger)tableView:(UITableView *)tableView
 numberOfRowsInSection:(NSInteger)section {

    if (section == 0) {
        return 4;
    }
    return 20;//行数
}

- (UITableViewCell *)tableView:(UITableView *)tableView
         cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//    UITableViewCell *aCell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:nil];
//    //为指定分区指定行设置显示的内容
//    aCell.textLabel.text = [NSString stringWithFormat:@"{%ld,%ld},???", indexPath.section, indexPath.row];
//    aCell.detailTextLabel.text = @"单元格的子标题";
//
//    //设置单元格被选中的样式, ios 7.0 以后 选中的样式一共只有两种可用 ,一种是选中没有样式, 一种是选中后显示灰色。
//    aCell.selectionStyle = UITableViewCellSelectionStyleDefault;
//
//    // 辅助视图样式
//    aCell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
//
//    // Cell 自带的 ImageView 是以单元格的高度为基准,按照图片的原始比例进行的缩放。
//    aCell.imageView.image = [UIImage imageNamed:@"shizi"];
//
//    if (indexPath.row == 2) {
//        aCell.imageView.image = [UIImage imageNamed:@"gril"];
//    }
//    //开关
//    UISwitch *aSwitch = [[UISwitch alloc] init];
//    aCell.accessoryView = aSwitch;
//    //微调器
////    UIStepper *aStepper  = [[UIStepper alloc] init];
////    aCell.accessoryView = aStepper;
//
//    return [aCell autorelease];

    /*
     重用机制是 tableView 提供的用于控制和优化内存的解决方案,其原理为:根据 tableView 的大小以及行高创建指定个数的单元格,当产生滑动时,一些暂时滑出 tableView 的单元格就会进入到 tableView 得重用队列被保存下来,等待下次继续使用,那么代理对象通过当前方法为 tableView 提供单元格对象时优先根据前指定的重用标识符获取重用队列中是否有可用的单元格,如果有,则重新为单元格添加数据,如果没有则创建新的单元格,然后添加数据,返回给表视图让其管理显示。
     */

    // 1、定义静态重用标识字符串。
    static NSString *identifier = @"CELL";
    // 2、根据给定的重用标识符从表视图的重用队列中获取可用单元格。
    UITableViewCell *aCell = [tableView dequeueReusableCellWithIdentifier:identifier];
    // 3、如果表视图的重用队列中没有可重用的单元格,则需要创建新的单元格。
    if (!aCell) {
        aCell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier] autorelease];
        // if 语句中可以为单元格一些通用属性赋值,例如可以为其辅助视图类型赋值,表示所有单元格的赋值样式都一致。
        aCell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;

    }
    //4、为单元格相关属性赋值,显示数据。
    aCell.textLabel.text = [NSString stringWithFormat:@"%@,%ld", aCell.textLabel.text, indexPath.row];;

    //单元格进入到重用队列后其子视图和展示的数据并不会被清除,从重用队列中得到的单元格需要重新利用,所以不能在当前方法无限制的为单元格添加子视图,会导致重影问题以及内存问题,相反我们可以通过子类化单元格的形式自定义其外观和展示。
//    UILabel *aLabel = [[UILabel alloc] initWithFrame:CGRectMake(100, 0, 200, 200)];
//    aLabel.textAlignment = NSTextAlignmentCenter;
//    aLabel.font = [UIFont systemFontOfSize:40];
//    aLabel.text = [NSString stringWithFormat:@"%d", arc4random() % 10 ];
//    [aCell addSubview:aLabel];
//    [aLabel release];

    //5、返回单元格给表视图
    return aCell;
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    //表视图默认拥有一个分区,我们可以通过此协议方法设置分区的个数
    return 6;
}

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {

    //为每一个分区指定分区区头标题
    return self.titles[section];
}

- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section {
    //为每一个分区指定分区区尾标题
    return @"区尾 标题";
}

- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
    //设置表视图分区的快速索引数组,该数组的内容需要与分区的区头标题一致,才可通过触摸快速切换分区。
    return self.titles;
}

//自定义区头视图,需要先通过协议方法设置区头视图的高度,再为表视图指定对应的视图的对象。
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
    return 40;
}

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
    UIView *view = [[UIView alloc] init];
    view.backgroundColor = [UIColor colorWithRed:arc4random() % 256 / 255.0 green:arc4random() % 256 / 255.0 blue:arc4random() % 256 / 255.0 alpha:1];
    return [view autorelease];
}

//自定义区尾视图,需要先通过协议方法设置区尾视图的高度,再为表视图指定对应的视图的对象。
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
    return 20;
}

- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section {
    UIView *view = [[UIView alloc] init];
    view.backgroundColor = [UIColor colorWithRed:arc4random() % 256 / 255.0 green:arc4random() % 256 / 255.0 blue:arc4random() % 256 / 255.0 alpha:1];
    return [view autorelease];
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    //除了 tableView 的 rowHeight 属性可以设置固定高度,我们还可以通过此协议方法根据需要展示的内容来设置各行的行高。
    return arc4random() % 71 + 30;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    //当点击某个单元格是会响应该方法,可以在此方法中做出对应的实现,比如创建新的视图控制器,对象通过导航控制器切换显示。
    DetailViewController *detailVC = [[DetailViewController alloc] init];
    detailVC.title = [NSString stringWithFormat:@"第%ld分区, 第%ld行", indexPath.section, indexPath.row ];
    [self.navigationController pushViewController:detailVC animated:YES];
    [detailVC release];
}

/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
}
*/

@end

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-09 21:50:25

UITableView 以及 UITableViewCell 的重用机制的相关文章

UITableViewCell的重用机制原理

UITableViewCell的重用机制原理 来自http://blog.csdn.net/omegayy/article/details/7356823 ========================================================== 创建UITableViewController子类的实例后,IDE生成的代码中有如下段落: - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowA

iOS基础篇(十三)——UITableView(一)重用机制

UITableView是app开发中常用到的控件,功能很强大,常用于数据的显示.在学习UITableView使用之前,我们先简单了解一下: 1.UITableView的重用机制 UITableView最核心的思想就是UITableViewCell的重用机制,对于一个UITableView而言,可能需要显示成百上千个Cell,如果每个cell都单独创建的话,会消耗很大的内存,为了避免这种情况,重用机制就诞生了. UITableView的重用机制的实现关键在于下面这个的函数:UITableViewC

UITableViewCell的重用机制和解决方法

UITableView为了做到显示与数据的分离, 单独使用了一个叫UITableViewCell的视图用来显示每一行的数据, 而tableView得重用机制就是每次只创建屏幕显示区域内的cell,通过重用标识符identifier来标记cell, 当cell要从屏幕外移入屏幕内时, 系统会从重用池内找到相同标识符的cell, 然后拿来显示, 这样本是为了减少过大的内存使用, 但在很多时候, 我们会自定义cell,这时就会出现一些我们不愿意看到的现象, 下面就介绍一些解决这些问题的方法 UITab

如何解决UITableViewCell因重用机制引起的重影问题

UITableView继承自UIScrollview,是苹果为我们封装好的一个基于scroll的控件.上面主要是一个个的UITableViewCell,可以让UITableViewCell响应一些点击事件,也可以在UITableViewCell中加入UITextField或者UITextView等子视图,使得可以在cell上进行文字编辑. UITableView中的cell可以有很多,一般会通过重用cell来达到节省内存的目的:通过为每个cell指定一个重用标识符(reuseIdentifier

UITableView动态存放、重用机制

一.UITableView动态存放 #import "ViewController.h"@interface ViewController ()<UITableViewDelegate,UITableViewDataSource>{     UITableView *tableview;     NSMutableArray *_arr;//盛放要显示的东西 }@end@implementation ViewController - (void)viewDidLoad {

UITableViewCell的重用机制

创建UITableViewController子类的实例后,IDE生成的代码中有如下段落: - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = [NSString stringWithFormat:@"Cell"]; UITableViewCell *cell =

【原】 从cellForRowAtIndexPath 看cell的重用机制

今天突然发现一个问题,由于对UITableViewCell 的重用机制不是很了解,让我纠结很久: 用过reloadData时候,会调用cellForRowAtIndexPath方法,但是请看以下2种cellForRowAtIndexPath 的写法: 写法A: -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{    static NSStri

使用重用机制创建cell的两种方法

一.UICollectionView使用的cell重用机制 1.首先服从<UICollectionViewDataSource>协议,如果自定义cell,导入自定义cell类的头文件 2.定义全局变量重用标识符 static NSString *cellIdentifier = @"重用"; 3.注册cell(collection,为UICollectionView对象) [collection registerClass:[UICollectionCell class]

UITableViewCell重用机制

1.UITableViewCell重用机制    1.cell使用重用的原因和重用机制的原理:      原因:     一个UITableView中有许多需要显示的cell,但是我们不可能每个都会浏览到,那么如果我们把这些数据全部都加载进去,是会造成内存的负担的.     我们所能显示的区域通常只有一个屏幕的大小,那么那些屏幕之外的信息是不需要一次性全都加载完的,只有当我们滑动屏幕需要浏览的时候,我们才需要它加载进来.因此,就有了我们要介绍的这部分内容,UITabelViewCell的重用机制