iOS-是否在不重新加载行的情况下更新UITableViewCell信息?

iOS-是否在不重新加载行的情况下更新UITableViewCell信息?,ios,uitableview,key-value,key-value-observing,Ios,Uitableview,Key Value,Key Value Observing,假设您有一个显示文件元数据列表的UITableView,您希望在自定义UITableViewCell的UILabel中显示每个文件的下载进度。(这是一个任意长的列表-因此将重用动态单元格) 如果要在不调用reloadData或reloadRowsAtIndexPaths的情况下更新标签,该如何操作 对于那些想知道的人-我不想调用任何一个重载…方法,因为在download\u progress上不需要为每个百分点的更新重新加载整个单元格 我遇到的唯一解决方案是: 添加单元格作为文件下载进度的键值

假设您有一个显示
文件
元数据列表的
UITableView
,您希望在自定义
UITableViewCell
UILabel
中显示每个文件的
下载进度
。(这是一个任意长的列表-因此将重用动态单元格)

如果要在不调用
reloadData
reloadRowsAtIndexPaths
的情况下更新标签,该如何操作

对于那些想知道的人-我不想调用任何一个
重载…
方法,因为在
download\u progress
上不需要为每个百分点的更新重新加载整个单元格

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

  • 添加单元格作为
    文件
    下载进度的键值观察者

  • 直接调用
    cellforrowatinexpath…
    获取标签并更改其文本

但是,, KVO通常不是一个有趣的api,当您将单元重用添加到混合中时,情况就更糟了。但是,每次添加一个百分点时直接调用
cellforrowatinexpath
会让人感觉脏兮兮的

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


谢谢。

我会创建一个自定义单元格,我猜您已经完成了。然后我会让手机监听下载进度方法将发布的特定通知,然后在那里更新标签。你必须找到一种方法让你的下载进度指定一个特定的单元格,可能是通过一个标题字符串或者一些可以告诉你的下载进度方法的独特的东西,这样你的单元格更新方法就可以确保注释是为它准备的。如果你需要我澄清我对这件事的想法,请告诉我

作为道格回答的必然结果,以下是我的结论:

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

我做了一个
FileNotificationType
enum(即
filenotificationtypedownloadtrigged
,和
filenotificationtypedownloaddrogress
)。然后,我会将进度与
FileNotificationType
一起发送到
NSNotification
userInfo-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];
    });
}
因此,在别处更新
文件的属性时,只需执行以下操作:

NSDictionary *attributes = @{@"download_progress" : @(<PROGRESS_INTEGER>)};
[file_instance postNotificationWithType:FileNotificationTypeDownloadProgress andAttributes:attributes];
最后,自定义的
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;
    }
}
-(无效)接收文件通知:(NSNotification*)通知
{
FileNotificationType=(FileNotificationType)[notification.userInfo[@“type”]integerValue];
//使用:[notification.userInfo valueForKey:@''访问更新的属性信息
开关(类型)
{
案例文件通知类型下载进度:
{
//对进展做点什么
打破
}
案例文件通知类型下载状态:
{
//对现状做些什么
打破
}
案例FSEpisodeNotificationTypeDownloadTriggered:
{
//如果触发下载,请执行某些操作
打破
}
违约:
打破
}
}
希望这能帮助那些希望更新tableview单元格而不必重新加载它们的人!观察键值的好处是,如果将
文件
对象与仍在观察的单元格解除分配,则不会出现问题。我也不必调用
cellForRow…


享受吧

您是否需要显示每个百分点的粒度的进度?你可以监控进度,只需每隔25%或更多的时间重新加载单元格?我想这是一种退路。iOS播客应用程序实际上很好地显示了持续的进度,而无需重新加载单元格。我想知道这是怎么做的…你也可以尝试在你的单元格中只中继一个自定义子视图的子视图树,它有进度指示器?通过设置一个标志,然后在调用
重新加载…
后只更新必要的子视图?唯一的问题是将重新计算单元格的高度,如果当前正在编辑该单元格(即显示右侧的“删除”按钮),则会突然将该单元格向右滑动。我想看看我是否可以不调用其中一个
重新加载
。是的,我可以尝试使用文件的唯一id作为名称的NSNotification。在单元格的生命周期中,您考虑在何处添加/删除作为观察者的单元格?在
tableviewWillDisplayCell…
中添加,在
TableViewDiEndDisplayingCell…
中删除?我还没有做到这一点,但你的建议可能是一个很好的地方。
- (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];
}
 - (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;
    }
}