不再使用时从 UITableViewCell 中删除观察者

Posted

技术标签:

【中文标题】不再使用时从 UITableViewCell 中删除观察者【英文标题】:Remove an observer from an UITableViewCell when not used anymore 【发布时间】:2013-11-15 14:19:54 【问题描述】:

在迁移到 ARC 后,我正在尝试调整我的项目。 我最大的问题是目前由于循环引用而没有释放对象。例如。在 UIView 上,不会调用 dealloc(我以前用它来释放对象并将它们置于 nil 上,因为这些对象正在阻止 dealloc。

对于 UIViews,我可以对“ViewDidDisappear”执行一些逻辑并确定不再需要它,但现在我遇到了 UITableViewCells 的问题。在一个中,我有一个通知观察者,如果创建了观察者,该单元格将保留在内存中。

检测是否不再需要(例如) UITableViewCell 的实例以便我可以删除观察者并且对象可以从内存中释放自身的最佳方法是什么?

这是我的标题:

@interface DOArticleListCell : DOPrototypeCell 
    IBOutlet UILabel *_title;
    IBOutlet UILabel *_summary;
    IBOutlet UILabel *_site;
    IBOutlet UILabel *_update;
    IBOutlet UILabel *_unpublished;
    IBOutlet UIButton *_readButton;

    __weak DOArticle *_article;
    NSNumber* _isEditor;


@property (nonatomic, weak) DOArticle *article;

- (void)updateReadButton;
- (IBAction)toggleReadButton:(id)sender;

@end

(原型单元只有一个名为“populateCell”的函数。)

附言。当打开选择单元格时调用的 detailViewController 时,我需要观察者更新“读取”标签。

【问题讨论】:

当您不希望引用使对象保持活动状态时,将代码设计为使用弱引用。 你真的需要观察者吗? 我需要观察者更新 tableview 上的“读取”标志。加载详细视图时,该项目被标记为已读,并且观察者由 ManagedObjectContextSave 通知触发并更新标签。我没有成功让另一个观察者更新 tableviewcell(当不在视图中时)。 NSFetchedResultsController 似乎没有在 tableview 上触发它,尽管它可能应该。 如果所有单元格的行为都相同,则应在 UITableViewCell 的dealloc 方法中删除观察者。如果不同的单元格表现不同,您应该在单元格的prepareForReuse 方法中将其删除。 我认为除非释放单元格,否则不会在 ARC 中调用 dealloc,这仅在删除观察者后才会发生。但我可以准备 prepareForReuse 并查看何时触发。 【参考方案1】:

您很可能不想在您的单元格上使用观察者。为什么不?您的细胞正在被重复使用。假设您的表格视图中有 400 个项目。在任何给定时间,屏幕上只会显示大约 8 个。这意味着只有 8 或 9 个单元格实例将保留在内存中,并在用户滚动时重新使用。这意味着每次单元格滚动到视野之外时,您都必须删除观察者,并且您需要为重复使用的单元格添加新的观察者。您可以通过覆盖单元格的prepareForReuse 方法来做到这一点。但是,不应在单元格中保存任何类型的状态(例如将单元格标记为“已读”),而应在您的模型中完成。

由于在您的情况下,用户操作触发了 read 状态的更新,您可以简单地将数据模型项设置为 readtableView:didSelectRowAtIndexPath: 中,然后通过调用自定义方法显式更新该单元格您的自定义单元格或致电[self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];

希望对你有帮助。

【讨论】:

这和我的建议差不多。 @Mundi 好吧,不完全是。我解释了为什么在细胞上使用观察者通常是一个坏主意,我指出了一个无观察者的解决方案。然而,我们都同意状态应该保存在模型中而不是单元格中,这是真的。对此的反对似乎有点苛刻。 @Mundi 哈哈哈,很公平 :) 我的错误 :) 周末愉快!【参考方案2】:

尽管有 ARC,你仍然可以在你的类中实现 -(void)dealloc 并调用

[[NSNotificationCenter defaultCenter] removeObserver:self name:@"yourNotName" object:nil]

【讨论】:

【参考方案3】:

您的观察者设计可能会得到改进。让包含视图的控​​制器成为您想要做出反应的任何东西的观察者似乎更方便。然后在视图控制器的viewWillDisappear 中移除自己作为观察者。

收到通知后,您只需更改表格视图的datasource。然后您可以检查应该获取它的单元格是否可见。如果是,请更新它,否则它应该在滚动到视图后自动显示新信息。

【讨论】:

以上是关于不再使用时从 UITableViewCell 中删除观察者的主要内容,如果未能解决你的问题,请参考以下文章

想要在单击相同的 UIButton 时从 UITableViewCell 更改正确的 UIButton 图像

选择时从 UITableViewCell 中消失的视图

当 SSL 证书不再有效时从 https 重定向到 http

扩展/收缩 UITableViewCell 高度不再适用于 iOS7

iOS:所选 UITableViewCell 的 UITextField 颜色错误

当我滚动时,uitableviewcell 中的 UIslider 不再自动更新