如何知道NSFetchedResultsChangeUpdate更改了哪个属性?

时间:2012-08-08 17:00:28

标签: ios uitableview core-data nsfetchedresultscontroller

我认为controller:didChangeObject:atIndexPath:forChangeType:newIndexPath:存在问题,特别是对于NSFetchedResultsChangeUpdate:它没有告诉您导致此NSFetchedResultsChangeUpdate的更改。

我有一个非常复杂的实体。其中只有一部分数据用于填充表格视图单元格。我不想更新我的单元格以进行任何不相关的属性更改 - 这是浪费资源。那么我怎么知道哪个属性更改导致了这个NSFetchedResultsChangeUpdate,这样我就可以避免更新我的表视图单元格呢?

3 个答案:

答案 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。