【问题标题】:UITableView shows wrong cell contentsUITableView 显示错误的单元格内容
【发布时间】:2014-04-23 05:51:16
【问题描述】:

我一直坚持使用 UITableView 并添加单元格。

我有基于 UITableView 的聊天应用程序来显示消息。当用户使用旧消息打开聊天时,一切正常。但是当用户添加新消息时 - 该消息的单元格填充了错误的内容。

我使用自定义单元格来显示消息。这是我的代码(简化):

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    // Im using storyboard, so I don't need if (!cell) part
    RightMessageCell *cell =  (RightMessageCell *) [self.messageTableView dequeueReusableCellWithIdentifier:@"right_text_message"];

    [self configureCell:cell forIndexPath:indexPath];

    return cell;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    [self configureCell:self.offscreenCell forIndexPath:indexPath];
     [self.offscreenCell setNeedsLayout];
     [self.offscreenCell layoutIfNeeded];

     result = [self.offscreenCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
}

- (void) configureCell:(RightMessageCell *) cell forIndexPath:(NSIndexPath *) indexPath {
    ChatMessageModel *message = [self.fetchController objectAtIndexPath:indexPath]; 
    rightMessageCell.messageTextView.text = message.messageText;
}

和FRC方法:

#pragma mark - NSFetchedResultsControllerDelegate
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
    [self.messageTableView beginUpdates];
}

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {
    switch(type) {
        case NSFetchedResultsChangeInsert:
            [self.messageTableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationNone];
            break;

        case NSFetchedResultsChangeDelete:
            [self.messageTableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationNone];
            break;

        case NSFetchedResultsChangeUpdate:
            [self.messageTableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationNone];
            break;
    }
}

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
    [self.messageTableView endUpdates];
}

但我不明白为什么新创建的单元格会带有以前的单元格内容并在重绘时替换它们自己的内容(例如,当我上下滚动时)

【问题讨论】:

  • 那是你的实际代码吗? configureCell:... 方法中的rightMessageCell 是什么?
  • @MartinR 它是消息单元的子类,为文本 messageTextView 提供出口
  • 我的意思是 rightMessageCell 变量,而不是 RightMessageCell 类。不应该是cell.messageTextView.text = ...吗?
  • @user2786037 我看到的和 Martin 一样。您将要配置的单元格传递给 configureCell,然后通过将消息文本设置到其他单元格 (rightMessageCell) 来忽略它。我的猜测是你需要使用 cell.messageTextView.text = ... 而不是 rightMessageCell...
  • @MartinR 哦,对不起,这是一个问题,而不是代码中的错误..

标签: ios objective-c uitableview


【解决方案1】:

在你的UITableViewCell 子类中你需要实现这个方法:

-(void)prepareForReuse {
    [super prepareForResuse];
    [self.textLabel setText:nil];
    // reset layout
    // reset text on your labels
    // reset other properties such as images or text colour
}

这是在 UITableViewCell 即将被重用之前调用的,因此您有机会将内容/布局重置为默认值。

我看到的另一个问题是cellrightMessageCell 这里:

- (void) configureCell:(RightMessageCell *) cell forIndexPath:(NSIndexPath *) indexPath {
    ChatMessageModel *message = [self.fetchController objectAtIndexPath:indexPath]; 
    rightMessageCell.messageTextView.text = message.messageText;
}

您的代码甚至应该无法使用上述方法进行编译。

【讨论】:

  • 当您遇到单元格短暂显示错误内容的问题或异步填充单元格内容时,这是一个不错的选择。在这种情况下,它不太可能产生太大影响,因为问题是长期的,并且只有在刷新单元格时才能解决。
  • 我相信有了那个sn-p,他的牢房里只会有一个空字符串。问题是重用单元格后文本设置不正确。
  • 我已经尝试过了,但我不明白为什么 text 不会被 cellForIndexPath 方法覆盖。另一个问题是如何重置布局。您能否详细说明为什么我应该将文本设置为 nil,即使我在 cellForIndexPath 方法中将文本设置为同一个出口并展示如何重置布局?
  • 如果您在重复使用单元格时设置文本,则绝对不必将文本设置为零。将图像和文本设置为 nil 始终是一个好主意,尤其是在异步加载图像时,占位符图像不会是最后显示的图像。
猜你喜欢
  • 2011-07-02
  • 1970-01-01
  • 2015-05-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多