使用UITableView时如何避免重绘效果?

时间:2021-08-16 06:53:40

I was debugging an issue with a view controller recently and noticed that each time I drag the view up or down it will repaint the entire contents of my UITableView (as it calls the cellForRowAtIndexPath method each time). Is it possible to use an in memory datasource or add another delegate to my view controller so it won't repaint each time?

我最近调试了一个视图控制器的问题并注意到每次我向上或向下拖动视图时它都会重新绘制我的UITableView的全部内容(因为它每次调用cellForRowAtIndexPath方法)。是否可以使用内存数据源或将另一个委托添加到我的视图控制器中,以便每次都不会重新绘制?

I'm not modifying anything inside the cells when the user interacts with it so my data source would be static after the initial "viewDidLoad" is called.

当用户与其交互时,我不会修改单元格内的任何内容,因此在调用初始“viewDidLoad”之后,我的数据源将是静态的。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    }

  if ([self.hats count] > 0) {
    //do some complex stuff in here that hurts each time we re-draw this ...
  }

    return cell;  
}

Thank you in advance

先谢谢你

1 个解决方案

#1


1  

so // complex stuff means adding UIViews.

所以//复杂的东西意味着添加UIViews。

I make an example for an UIImageView. Since you don't show the complex stuff you have to adopt it on your own.

我为UIImageView做了一个例子。由于您没有展示复杂的东西,您必须自己采用它。

your code looks like this:

你的代码看起来像这样:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    }

    if ([self.hats count] > 0) {
        UIImageView *imageView = [[UIImageView....];
        [cell.contentView addSubView:imageView];
        [imageView setImage:foo];
        [imageView release];
    }
    return cell;
}

refactor your code that it looks like this:

重构你的代码看起来像这样:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
        UIImageView *imageView = [[UIImageView....];
        [cell.contentView addSubView:imageView];
        imageView.tag = 42;
        [imageView release];
    }

    if ([self.hats count] > 0) {
        UIImageView *imageView = [cell viewWithTag:42];
        [imageView setImage:foo];
    }
    return cell;
}

et voila, your tableview is responsive. Because you create the subviews exactly one time for each cell. And when the cell isn't used anymore and goes into the reuse bin the subviews stay with it.

et voila,你的tableview是响应。因为您为每个单元格准确创建了一次子视图。当细胞不再使用并进入重复使用区时,子视图将继续使用它。

And if you need 4 imageViews in one cell and 8 in another, you add 8 imageviews when you create the cell and give them a frame of CGRectZero and of course a different tag for each view.
If you need them you show them, if you don't need them you set the image to nil and the frame to zero.

如果您在一个单元格中需要4个图像视图而在另一个单元格中需要8个图像视图,则在创建单元格时添加8个图像视图并为其提供一个CGRectZero框架,当然每个视图都有一个不同的标记。如果您需要它们,则显示它们,如果您不需要它们,则将图像设置为nil,将帧设置为零。

#1


1  

so // complex stuff means adding UIViews.

所以//复杂的东西意味着添加UIViews。

I make an example for an UIImageView. Since you don't show the complex stuff you have to adopt it on your own.

我为UIImageView做了一个例子。由于您没有展示复杂的东西,您必须自己采用它。

your code looks like this:

你的代码看起来像这样:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    }

    if ([self.hats count] > 0) {
        UIImageView *imageView = [[UIImageView....];
        [cell.contentView addSubView:imageView];
        [imageView setImage:foo];
        [imageView release];
    }
    return cell;
}

refactor your code that it looks like this:

重构你的代码看起来像这样:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
        UIImageView *imageView = [[UIImageView....];
        [cell.contentView addSubView:imageView];
        imageView.tag = 42;
        [imageView release];
    }

    if ([self.hats count] > 0) {
        UIImageView *imageView = [cell viewWithTag:42];
        [imageView setImage:foo];
    }
    return cell;
}

et voila, your tableview is responsive. Because you create the subviews exactly one time for each cell. And when the cell isn't used anymore and goes into the reuse bin the subviews stay with it.

et voila,你的tableview是响应。因为您为每个单元格准确创建了一次子视图。当细胞不再使用并进入重复使用区时,子视图将继续使用它。

And if you need 4 imageViews in one cell and 8 in another, you add 8 imageviews when you create the cell and give them a frame of CGRectZero and of course a different tag for each view.
If you need them you show them, if you don't need them you set the image to nil and the frame to zero.

如果您在一个单元格中需要4个图像视图而在另一个单元格中需要8个图像视图,则在创建单元格时添加8个图像视图并为其提供一个CGRectZero框架,当然每个视图都有一个不同的标记。如果您需要它们,则显示它们,如果您不需要它们,则将图像设置为nil,将帧设置为零。