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

时间:2015-04-26 02:44:18

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

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

如果您想更新标签而不致电reloadDatareloadRowsAtIndexPaths,您怎么做?

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

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

  • 将细胞添加为file download_progress的键值观察者。

  • 直接致电cellForRowAtIndexPath...获取标签并更改其文字。

然而, 一般来说KVO不是一个有趣的api - 当你在混合中添加细胞再利用时更是如此。每次添加百分点时直接调用cellForRowAtIndexPath都会感觉很脏。

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

感谢。

2 个答案:

答案 0 :(得分:2)

作为Doug的回应的必然结果,这就是我最终的目标:

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

我制作了FileNotificationType枚举(即FileNotificationTypeDownloadTriggeredFileNotificationTypeDownloadProgress)。然后我会将进度与NSNotification一起发送到userInfo NSDictionary的{​​{1}}。

FileNotificationType

- (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:

希望这可以帮助那些想要更新tableview单元而无需重新加载它们的人!关键值观察的好处是,如果 - (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

享受!

答案 1 :(得分:1)

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