【问题标题】:UITableViewCell randomly disappears + scrolling performance issue on iPhone 4UITableViewCell 随机消失 + iPhone 4 上的滚动性能问题
【发布时间】:2013-09-03 08:38:03
【问题描述】:

总而言之,我面临 2 个问题,第一个是有时某些单元格会从 tableview 中消失并随机重新出现。第二个是 iPhone 4 及以下的滚动性能问题。

第一个问题:

我通过添加 [cell contentView] 的子视图在 UITableView 中显示一个简单的元素列表。大多数情况下它运行良好,但有时当我滚动(并且非常随机)时,一个单元格会消失。

因为这个“消失”的单元格被重复使用,所以当我滚动时,重复使用的单元格也将是“空白”。滚动时,一个单元格会再次随机出现/消失。

这是我的 cellForRowAtIndexPath: 方法代码:

- (UITableViewCell *)tableView:(UITableView *)_tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [_tableView dequeueReusableCellWithIdentifier:CellIdentifier];
LBSelectorChampionViewController *item = [self itemAtIndexPath:indexPath];
if (cell == nil) {
    NSLog(@"CELL NIL");
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];

    [[item view] setTag:99];
    [[item champName] setTag:50];
    [[item champImage] setTag:51];
    [[item buttonFavorite] setTag:52];
    [[cell contentView] addSubview:[item view]];
}

UILabel *championLabel =  (UILabel*)[[[cell contentView] viewWithTag:99] viewWithTag:50];
LBFavoriteChampionButton *buttonFavorite = (LBFavoriteChampionButton*)[[[cell contentView] viewWithTag:99] viewWithTag:52];
UIImageView *championImage = (UIImageView*)[[[cell contentView] viewWithTag:99] viewWithTag:51];

// Text
[championLabel setText:[item displayValue]];

[championImage setImageWithURL:[NSURL URLWithString:[item imageUrl]]];

// Fav button
[buttonFavorite setCurrentChampion:item];
if ([[self favoritesChampions] containsObject:item]) {
    [buttonFavorite setSelected:YES];
    [buttonFavorite setIsFavorite:YES];
} else {
    [buttonFavorite setSelected:NO];
    [buttonFavorite setIsFavorite:NO];
}
return cell;}
}

我已尝试记录所有内容,我检查了“item”是否有时可能为空,但事实并非如此。但是当一个单元格消失时,[[[cell contentView] subviews] count]等于0,通常应该是1。 我真的不明白这里发生了什么。我在真实设备+模拟器上对其进行了测试,两者都发生了。

第二个问题:

我的另一个“问题”是 tableview 的滚动不像我期望的那样平滑,因为它在 iPhone 4 上(在 iOS 6 和 iOS 7 上测试,相同的结果 :-( )。我正在使用SDWebImage 异步加载图片并缓存,我在重用cell,如何提高性能?我在iPhone 4S上测试,没有问题,滚动非常流畅。

我做错了吗?关于我的一个问题有什么想法吗?

感谢您花时间回答我。

编辑:第一次尝试解决问题

尝试使用自定义 UITableViewCell 子类自定义单元格:

- (UITableViewCell *)tableView:(UITableView *)_tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"LBListChampionCell";

LBListChampionCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

if (cell == nil){
    NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"LBListChampionCell" owner:self options:nil];
    cell = [topLevelObjects objectAtIndex:0];
}
LBSelectorChampionViewController *item = [self itemAtIndexPath:indexPath];
[[cell championName] setText:[item displayValue]];
[[cell championLogo] setImageWithURL:[NSURL URLWithString:[item imageUrl]]];
return cell;
}

我暂时无法重现“消失”的错误(有时重现它需要一些时间......),但性能方面没有任何改善:(。即使只是设置一个dummy text : [[cell ChampionName] setText:@"Test"]; (并评论项目部分)滚动仍然不是很流畅。

有什么想法吗?

编辑 2:最佳解决方案(感谢 rdelmar)

创建 UITableViewCell 的子类并在 viewDidLoad 中加载 nib:

- (void)viewDidLoad
{
    ...
    UINib *nib = [UINib nibWithNibName:@"LBListChampionCell" bundle:nil];
    [[self tableView] registerNib:nib forCellReuseIdentifier:@"LBListChampionCell"];
}

- (UITableViewCell *)tableView:(UITableView *)_tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    LBListChampionCell *cell =  [tableView dequeueReusableCellWithIdentifier:@"LBListChampionCell"];
    LBSelectorChampionViewController *item = [self itemAtIndexPath:indexPath];
    [[cell championName] setText:[item displayValue]];
    [[cell championLogo] setImageWithURL:[NSURL URLWithString:[item imageUrl]]];
    ...
}

它提高了滚动性能(在 iPhone 4 上仍然不是很流畅,但效果很好)。此外,似乎没有细胞消失了:-)

感谢 rdelmar!

【问题讨论】:

  • 这段代码中的 self 是什么(您发布的代码所在的类的超类是什么)? item 是一个视图控制器,并且您将其视图添加为单元格的子视图?这似乎是一个奇怪的结构。
  • self 也是一个视图控制器,它包含了tableview。我应该避免将另一个视图控制器的视图添加为单元格的子视图吗?
  • 是的,我认为你应该避免这种情况。控制器的视图不应该被共享(当您将控制器的视图添加到另一个视图时,它应该成为子视图控制器)。为什么这一切都在代码中?为什么不在 xib 或情节提要中设置一个包含任何您想要的子视图的自定义单元格?
  • 好的,谢谢你的提示。但是在单元格的内容视图中加载 xib 的最佳做法应该是什么?
  • 我试图创建一个 UITableViewCell 子类(参见我上面的编辑),希望它能提高性能,但它没有:(。

标签: iphone ios objective-c uitableview


【解决方案1】:

我认为由于单元可重用性,您遇到了第一个问题。 LBSelectorChampionViewController *item = [self itemAtIndexPath:indexPath]; 不会总是添加到 [cell contentView] 因为单元格可能不是 nil。此外,可能会出现此视图将添加到另一个单元格并从前一个单元格中删除的情况。无论如何,如果您继承 UITableViewCell 并使 LBSelectorChampionViewController 成为此自定义单元格的一部分,这将更容易解决。这将使一切变得更容易,并且您将永远不会遇到可重用性问题。

我对 SDWebImage 并不十分熟悉,但问题可能在于它不会缓存图像,并且每次点击[championImage setImageWithURL:[NSURL URLWithString:[item imageUrl]]]; 时都会尝试加载新图像。我在一些项目中使用AFNetworking 来加载图像并且从未遇到任何问题。

希望这有帮助! 干杯!

【讨论】:

  • 当第一个单元格显示时,单元格为零,之后它们被重用。这就是为什么我使用标签和“项目”来改变标签和图像的值。正如我所说,“item”永远不会为零,并且每次都有正确的值,但就像它没有将它应用于单元格:s.
【解决方案2】:

我认为您的一个单元格的 contentView 中的 LBSelectorChampionViewController *item = [self itemAtIndexPath:indexPath]; 不知何故被添加到另一个单元格的 contentView 中,这将导致前一个单元格的 contentView 有 0 个子视图。

【讨论】:

  • 似乎不是因为显示的项目顺序很好并且保留了。这意味着如果一个单元格没有显示出来,下面的单元格仍然是好的并且顺序正确。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-05
  • 2017-07-31
相关资源
最近更新 更多