【问题标题】:iOS- Update UITableViewCell information without reloading the row?iOS-在不重新加载行的情况下更新 UITableViewCell 信息?
【发布时间】:2015-07-04 13:40:03
【问题描述】:

假设您有一个显示file 元数据列表的UITableView,并且您希望在自定义UITableViewCellUILabel 中显示每个文件的download_progress。 (这是一个任意长的列表 - 因此动态单元格将被重用)。

如果您想在不调用reloadDatareloadRowsAtIndexPaths 的情况下更新标签,该怎么做?

对于那些想知道的人 - 我不想调用任何一个 reload... 方法,因为没有必要为 download_progress 上的每个百分点更新重新加载整个单元格。

我遇到的唯一解决方案是:

  • 将单元格添加为filedownload_progress 的键值观察器。

  • 直接调用cellForRowAtIndexPath...获取标签并修改其文字。

然而, 一般来说,KVO 不是一个有趣的 api,当您将单元重用添加到组合中时更是如此。但是,每次添加一个百分点时直接调用cellForRowAtIndexPath 感觉很脏。

那么,有哪些可能的解决方案?任何帮助将不胜感激。

谢谢。

【问题讨论】:

  • 您是否需要按每个百分点的粒度显示进度?你可以只监控进度,然后每 25% 重新加载一次单元格吗?
  • 我想这将是后备。 iOS 播客应用程序实际上可以很好地显示连续进度而无需重新加载单元格。我想知道它是如何完成的......
  • 您也可以尝试仅在具有进度指示器的单元格中中继自定义子视图的子视图树?
  • 通过设置标志然后只在调用reload... 后更新必要的子视图?唯一的问题是单元格的高度将被重新计算,如果当前正在编辑单元格(即在右侧显示“删除”按钮),那么它将突然将单元格滑回右侧。我想看看我是否可以不打电话给reloads 之一。

标签: ios uitableview key-value key-value-observing


【解决方案1】:

我会创建一个自定义单元格,我猜你已经完成了。然后,我会让单元侦听您的下载进度方法将发布的特定通知,然后在那里更新标签。您必须找到一种方法让您的下载进度指定某个单元格,可能是通过标题字符串或可以告诉您的下载进度方法的唯一内容,因此您的单元格更新方法可以确保注释是意味着它。如果您需要我澄清我对此的思考过程,请告诉我。

【讨论】:

  • 是的,我可以尝试使用文件的唯一 ID 作为名称的 NSNotification。您在单元的生命周期中的哪个位置考虑添加/删除单元作为观察者?添加tableviewWillDisplayCell... 并删除tableviewDidEndDisplayingCell...?
  • 我还没有走那么远,但你的建议可能是一个很好的地方。
【解决方案2】:

作为 Doug 回应的推论,我最终得出的结论是:

每个file 都有一个唯一标识符,所以我让它负责发布有关其属性更新的通知(想想 KVO,但没有麻烦):

我创建了一个FileNotificationType 枚举(即FileNotificationTypeDownloadTriggeredFileNotificationTypeDownloadProgress)。然后我会将进度与FileNotificationType 一起发送到NSNotificationuserInfo NSDictionary

- (void)postNotificationWithType:(FileNotificationType)type andAttributes:(NSDictionary *)attributes
{
    NSString *unique_notification_id = <FILE UNIQUE ID>;

    NSMutableDictionary *mutable_attributes = [NSMutableDictionary dictionaryWithDictionary:attributes];
    [mutable_attributes setObject:@(type) forKey:@"type"];

    NSDictionary *user_info = [NSDictionary dictionaryWithDictionary:mutable_attributes];

    dispatch_async(dispatch_get_main_queue(), ^{
    [[NSNotificationCenter defaultCenter] postNotificationName:unique_notification_id object:nil userInfo:user_info];
    });
}

file 对象还有一个方法可以枚举它可以发送哪些类型的通知:

- (NSArray *)notificationIdentifiers
{
    NSString *progress_id = <FILE UNIQUE ID + FILENOTIFICATIONTYPE>;
    NSString *status_id = <FILE UNIQUE ID + FILENOTIFICATIONTYPE>
    NSString *triggered_id = <FILE UNIQUE ID + FILENOTIFICATIONTYPE>

    NSArray *identifiers = @[progress_id, status_id, triggered_id];
    return identifiers;
}

因此,当您在别处更新 file 的属性时,只需执行以下操作:

NSDictionary *attributes = @{@"download_progress" : @(<PROGRESS_INTEGER>)};
[file_instance postNotificationWithType:FileNotificationTypeDownloadProgress andAttributes:attributes];

在接收端,我的表视图委托实现了这些方法来添加/删除我的自定义 UITableViewCells 作为这些通知的观察者:

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
    File *file = [modelObject getFileAtIndex:indexPath.row];
    for (NSString *notification_id in file.notificationIdentifiers)
    {
        [[NSNotificationCenter defaultCenter] addObserver:cell selector:@selector(receiveFileNotification:) name:notification_id object:nil];
    }
}

- (void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
    [[NSNotificationCenter defaultCenter] removeObserver:cell];
}

最后,自定义的UITableViewCell 必须实现receiveFileNotification: 方法:

 - (void)receiveFileNotification:(NSNotification *)notification
{
    FileNotificationType type = (FileNotificationType)[notification.userInfo[@"type"] integerValue];

    // Access updated property info with: [notification.userInfo valueForKey:@"<Your key here>"]

    switch (type)
    {
        case FileNotificationTypeDownloadProgress:
        {
            // Do something with the progress
            break;
        }
        case FileNotificationTypeDownloadStatus:
        {
            // Do something with the status
            break;
        }
        case FSEpisodeNotificationTypeDownloadTriggered:
        {
            // Do something if the download is triggered
            break;
        }
        default:
            break;
    }
}

希望这可以帮助那些希望更新表格视图单元格而无需重新加载它们的人!比键值观察的好处是,如果 File 对象在单元格仍在观察的情况下被释放,您将不会遇到问题。我也不必打电话给cellForRow...

享受吧!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-01-20
    • 1970-01-01
    • 2021-09-13
    • 1970-01-01
    • 2021-01-10
    • 1970-01-01
    • 1970-01-01
    • 2014-01-10
    相关资源
    最近更新 更多