Apple 通过创建一个保留托管对象的 UITableViewCell 子类(良好的 KVO 实践)来实现此优化(在 MobileNotes 中),并在自定义设置器中为感兴趣的属性添加 KVO,但如果前一个对象存在,则首先删除前一个对象的 KVO。在 prepareForReuse 中,它将对象设置为 nil。在 dealloc 中,如果 _object 不为零,它会删除 KVO。
这是我的通用演示类,但是最好将代码复制到您的类中,而不是子类化;重命名对象属性:
MCDManagedObjectTableViewCell.h
#import <CoreData/CoreData.h>
#import <UIKit/UIKit.h>
#import <MCoreData/MCDDefines.h>
NS_ASSUME_NONNULL_BEGIN
MCDATA_EXTERN void * const MCDManagedObjectTableViewCellKVOContext;
@interface MCDManagedObjectTableViewCell<__covariant ManagedObjectType : __kindof NSManagedObject *> : UITableViewCell
// needs to be retained to prevent being turned into a fault
@property (nullable, strong, nonatomic) ManagedObjectType object;
// overrides
// update views from the object's properties
- (void)updateViewsFromCurrentObject NS_REQUIRES_SUPER;
// calls update if on screen otherwise sets a flag and then updates when comes on screen.
- (void)updateViewsFromCurrentObjectIfNecessary NS_REQUIRES_SUPER;
// use addObserver and the MCDManagedObjectTableViewCellKVOContext
- (void)addKVOObserversForObject:(ManagedObjectType)object;
- (void)removeKVOObserversForObject:(ManagedObjectType)object;
@end
NS_ASSUME_NONNULL_END
MCDManagedObjectTableViewCell.m
#import "MCDManagedObjectTableViewCell.h"
void * const MCDManagedObjectTableViewCellKVOContext = (void *)&MCDManagedObjectTableViewCellKVOContext;
@interface MCDManagedObjectTableViewCell ()
@property (nonatomic) BOOL needsToUpdateViews;
@end
@implementation MCDManagedObjectTableViewCell
- (void)setObject:(__kindof NSManagedObject *)object{
if(_object == object){
return;
}
else if(_object){
[self removeKVOObserversForObject:_object];
}
_object = object;
if(object){
[self addKVOObserversForObject:object];
}
[self updateViewsFromCurrentObjectIfNecessary];
}
- (void)addKVOObserversForObject:(__kindof NSManagedObject *)object{
}
- (void)removeKVOObserversForObject:(__kindof NSManagedObject *)object{
}
- (void)observeValueForKeyPath:(nullable NSString *)keyPath ofObject:(nullable id)object change:(nullable NSDictionary<NSKeyValueChangeKey, id> *)change context:(nullable void *)context{
if(context != MCDManagedObjectTableViewCellKVOContext){
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
return;
}
[self updateViewsFromCurrentObjectIfNecessary];
}
- (void)updateViewsFromCurrentObject{
self.needsToUpdateViews = NO;
}
- (void)updateViewsFromCurrentObjectIfNecessary{
if(self.window){
[self updateViewsFromCurrentObject];
}else{
self.needsToUpdateViews = YES;
}
}
- (void)willMoveToWindow:(UIWindow *)window{
if(window && self.needsToUpdateViews){
[self updateViewsFromCurrentObject];
}
}
- (void)prepareForReuse{
[super prepareForReuse];
self.object = nil;
}
- (void)dealloc{
if(_object){
[self removeKVOObserversForObject:_object];
}
}
@end
此外,如果单元格需要显示依赖于多个属性的字符串,则可以将自定义属性(例如 titleForTableViewCell)添加到模型子类中,并且可以使用“受其影响的键”机制并在该单个属性上使用 KVO。