2

我认为有一个问题controller:didChangeObject:atIndexPath:forChangeType:newIndexPath:,具体为NSFetchedResultsChangeUpdate:它没有告诉你是什么变化导致了这个NSFetchedResultsChangeUpdate

我有一个非常复杂的实体。只有一部分数据用于填充我的表格视图单元格。我不想为任何不相关的属性更改更新我的单元格——这是对资源的浪费。那么我如何知道是哪个属性更改导致了这种NSFetchedResultsChangeUpdate情况,以便在不相关的情况下避免更新我的表格视图单元格?

4

3 回答 3

1

您可以将分配给单元格的值与更改的 NSManagedObject 中的属性值进行比较。假设您在自定义单元格上使用 3 个标签,并且您的对象有更新,您可以向单元格子类添加一个方法并传递 NSManagedObject 询问单元格是否需要更新。该单元格将验证 NSManagedObject 的值并将它们与标签的值进行比较。如果它们不相等,则需要更新。您可以从您在问题上发布的委托方法的索引路径访问单元格。

于 2012-08-08T21:26:25.237 回答
1

NSManagedObject有两种方法。首先返回一个字典,其中包含自上次获取或保存对象以来已更改的键和(新)值(这在没有触发关系错误的情况下有效地实现)

- (NSDictionary *)changedValues;

第二:

- (NSDictionary *)changedValuesForCurrentEvent NS_AVAILABLE(10_7, 5_0);

您通过NSFetchedResultsController调用他们的NSFetchedResultsChangeUpdate通知

于 2013-08-16T10:45:55.370 回答
0

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。

于 2018-04-17T10:36:20.313 回答