iOS-更新 UITableViewCell 信息而不重新加载行?

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

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

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

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

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

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

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

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

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

谢谢。

最佳答案

作为 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;
}

因此,当您在其他地方更新文件 的属性时,只需执行以下操作:

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

在接收端,我的 TableView 委托(delegate)实现了这些方法来添加/删除我的自定义 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;
    }
}

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

尽情享受吧!

关于iOS-更新 UITableViewCell 信息而不重新加载行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29873097/

相关文章:

objective-c - iOS:如何将 key 发送到 UITextField?

json - 从 JSON 数据向 TableView 添加部分

ios - 如何使用搜索栏过滤字典数组

database - cdb - 大文件(数百 GB)的常量键值存储

javascript - JS在键值对数组中查找特定键

ios - 在 UIWebView 上覆盖一个刷新按钮

ios - UIView的animateWithDuration延迟不延迟动画

ios - 点击 didSelectRow 以转到另一个 View Controller 时崩溃

ios - 无效更新 : invalid number of rows in section

javascript - 带键值的数组长度,js