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には、そのための 2 つのメソッドがあります。最初に、オブジェクトの最後のフェッチまたは保存以降に変更されたキーと (新しい) 値を含む辞書を返します (これは、リレーションシップ フォールトを発生させずに効率的に実装されます)。

- (NSDictionary *)changedValues;

2番:

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

NSFetchedResultsController によって NSFetchedResultsChangeUpdate通知を呼び出します。

于 2013-08-16T10:45:55.370 に答える
0

Apple は、管理対象オブジェクトを保持する UITableViewCell サブクラスを作成することで (MobileNotes で) この最適化を実現し (KVO の適切な実践)、カスタム セッターで対象のプロパティに 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 を使用できます。

于 2018-04-17T10:36:20.313 に答える