我认为controller:didChangeObject:atIndexPath:forChangeType:newIndexPath:
存在问题,特别是对于NSFetchedResultsChangeUpdate
:它没有告诉您导致此NSFetchedResultsChangeUpdate
的更改。
我有一个非常复杂的实体。其中只有一部分数据用于填充表格视图单元格。我不想更新我的单元格以进行任何不相关的属性更改 - 这是浪费资源。那么我怎么知道哪个属性更改导致了这个NSFetchedResultsChangeUpdate
,这样我就可以避免更新我的表视图单元格呢?
答案 0 :(得分:1)
您可以将分配给单元格的值与更改的NSManagedObject中的属性值进行比较。假设您在自定义单元格上使用了3个标签,并且对对象进行了更新,可以向单元子类添加方法,并传递NSManagedObject,询问单元格是否需要更新。单元格将验证NSManagedObject的值,并将它们与标签的值进行比较。如果它们不相等,则需要更新。您可以从您在问题上发布的委托方法的索引路径访问单元格。
答案 1 :(得分:1)
NSManagedObject 有两种方法。首先返回一个字典,其中包含自上次获取或保存对象以来已更改的键和(新)值(这是在没有触发关系错误的情况下有效实现的)
- (NSDictionary *)changedValues;
第二
- (NSDictionary *)changedValuesForCurrentEvent NS_AVAILABLE(10_7, 5_0);
您通过 NSFetchedResultsController
在 NSFetchedResultsChangeUpdate 上调用他们的通知答案 2 :(得分:0)
Apple通过创建保留托管对象的UITableViewCell子类(良好的KVO实践)来实现此优化(在MobileNotes中),并且在自定义setter中为感兴趣的属性添加KVO,但是如果存在,则首先删除前一个对象的KVO是一个。在prepareForReuse中,它将对象设置为nil。在dealloc中,如果_object不是nil,它将删除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。