关于cell的循环利用

来源:互联网 发布:linux创建新用户命令 编辑:程序博客网 时间:2024/05/15 12:32

1:为什么会出现cell的循环利用呢,那我们就先来谈一下关于这个方法的调用

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

 

上面这个方法想必大家都很熟悉吧,他是我们TableView数据源方法里面必须实现的方法,当有新的cell要显示在界面上的时候,这个方法就会被调用,下面假设我们想要显示10个cell,如果用下面的方法,那么这个我们就要创建10个cell,那也就意味着如果我们要显示1000,10000条数据,我们也要创建1000,10000个cell,那随着数据的增多,我们的系统就会分配更多的内存空间,这个性能也太差了吧!

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

UITableViewCell *cell= [[UITableViewCell alloc]init];

    cell.textLabel.text = [NSString stringWithFormat:@"%zd",indexPath.row];

    return cell;

-      

-     }

于是关于cell的复用就被我们带出来了,我用一个例子解释一下我所理解的cell的复用原理

假设我要现实50条数据,在我设置完tableView的frame以及cell的高度,假设屏幕上现在能显示5个cell,那么系统在创建cell的时候会先去缓冲池里面寻找与我们要创建的cell相同类型的可被重新利用的cell,那么就牵扯到我们缓冲池什么时候才会有可以循环利用的cell呢,那就是当我们拖动tableView时有一个cell将要离开屏幕的时候,这个cell就会被系统放进缓冲池里面,备用,所以当我们程序启动后,他屏幕上最多能显示5个cell,所以创建cell的代码就会被执行5次,当前缓冲池里面是空的,当我们开始拖动tableView,当第0个cell快要离开屏幕,第5个cell快要出现时,cell被创建的代码又会被执行一次,因为第0个cell还没有完全离开屏幕,所以我们当前的缓冲池仍然是空的,当第5个cell被创建好完全显示在屏幕上的时候,第0个cell也敲好完全离开了屏幕,进入到了缓冲池,这时候我们继续拖动cell,这时候要创建第6个cell了,我们系统会按照他原来的路线先去缓冲池里面查找有没有可以服用的cell,这时候他会发现,咦,这里刚好有一个不用的cell,那么系统就会把这个celll从缓冲池里面取出来,然后不去创建cell,而是直接用从缓冲池里面取出来的没有清空原有数据的cell,后面的同理,大家数一下,我们是不是只创建了屏幕上可现实的cell个数+1个cell,我们要显示50条数据,结果就创建了6个cell,是不是性能大大优化了,但是我在说了上面一大段话的时候,有两个特别用红色部分标注的部分,下面我会在代码中提到,(请注意下面代码中的红色部分)好了,做了这么多铺垫,我们就实战一下吧

cell的复用有两种方式,而这两种方式的区别在于cell由谁来创建

1:通过手动创建cell来实现cell的循环利用

- (void)viewDidLoad {

    [super viewDidLoad];

    

    self.tableView = [[UITableView alloc]initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width,self.view.bounds.siz e.height) style:UITableViewStylePlain];

    self.tableView.backgroundColor = [UIColor lightGrayColor];

    self.tableView.delegate = self;

    self.tableView.dataSource  = self;

    [self.view addSubview:self.tableView];

}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{

    return 100;

}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{

    return 100;

}


static int count = 0;

/*-----------cell的循环利用------------------------*/

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

  //第一步:定义静态标识符:原因因为缓存池里面可能有多种不同类型的cell,你不能随便拿出来一个cell就用,所以我们要标识我们的cell,让系统知道他去缓冲池找的时候找的是啥样的cell,这就是我第一处标注的地方

    static NSString *identity = @"hello";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identity];

    if (cell==nil) {

        count = count+1;

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

       

    }

    else

    {

        //删除cell的所有子视图

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

        {

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

        }

       

    }//如果我们将自定义的控件加在了cell上,那么一定要加上这个判断,将cell上的子视图全部移除,下面重新赋值,不然必会发现数据重叠的现象,因为系统只负责取出cell,并不会帮我们处理cell上的数据,如果是cell上自带的控件,则不用移除,例如cell.TextLable,他会对cell重新赋值

    UILabel *lable = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, 200, 40)];

    lable.text =  [NSString  stringWithFormat:@"testdata_%zd",indexPath.row];

    [cell.contentView addSubview:lable];

    

    NSLog(@"%d",count);

    return cell;

    

}


第二种方式,注册cell,让系统自动帮我们创建cell,代码分散

static NSString *ID = @"hello";//因为VieDidLoad里面也要用

- (void)viewDidLoad {

    [super viewDidLoad];

    

    self.tableView = [[UITableView alloc]initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width,self.view.bounds.size.height) style:UITableViewStylePlain];

    //注册某个标识对应的cell类型,只能在这里注册,因为他只能止住一次,要是在下面的方法里,他会注册多次,会报错,只能是默认样式的cell

  [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:ID];//第一个参数,拿到cell的类型,通过hello标识去缓存池里面找不到cell,就创建uitableViewCell类型的cell给你

    self.tableView.backgroundColor = [UIColor lightGrayColor];

    self.tableView.delegate = self;

    self.tableView.dataSource  = self;

    [self.view addSubview:self.tableView];

}


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

    //定义重用标识符

    //取缓存池里面查找cell,因为在ViewDieLoad里面已经注册过,所以当缓存池里面没有cell时会帮我们自动创建

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];

            //删除cell的所有子视图

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

            {

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

            }

    //赋值

        UILabel *lable = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, 200, 40)];

        lable.text =  [NSString  stringWithFormat:@"testdata_%zd",indexPath.row];

        [cell.contentView addSubview:lable];

    return cell;

}


因为我是个菜鸟,所以理解如果有什么问题的话,欢迎大家指出错误或者提出意见,谢谢大家



 

0 0
原创粉丝点击