2

NSManagedObject1対多の関係を持つサブクラスと、その関係にあるオブジェクトのフィルタリングされたサブセットを提供するためにデータ モデルに設定されたフェッチされたプロパティがあります。

//School.h
@interface School : NSManagedObject
@property (nonatomic, retain) NSSet *pupils;
@property (nonatomic, retain) NSArray *starPupuils;
@end

//School.m
@implementation School
@dynamic pupils;
@dynamic starPupils;
@end

次に、School オブジェクトで生徒の変更を監視し、starPupils データを更新するビュー コントローラーを作成します。

-(void)setSchool:(School *)school
{
    …
    self.contentArray = [self.school starPupils];
    [self.school addObserver:self
                  forKeyPath:@"pupils"
                     options:nil
                     context:nil];
    …
}

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if ([keyPath isEqualToString:@"pupils"])
    {
        self.contentArray = [self.school starPupils];
    }
}

これは、フェッチされたプロパティが最初にアクセスされたときに正常に機能しますが、予想どおり starPupils 配列がキャッシュされ、瞳孔が追加および削除されるときにそれ自体が更新されません。

宛先エンティティのオブジェクトが変更された場合は、フェッチされたプロパティを再評価して最新であることを確認する必要があります。プロパティを手動で更新するために使用refreshObject:mergeChanges:します。これにより、オブジェクトの障害が次に発生したときに、このプロパティに関連付けられたフェッチ リクエストが再度実行されます。—コア データ プログラミング ガイド: リレーションシップとフェッチされたプロパティ

私の質問は、どこrefreshObject:mergeChanges:から電話をかければよいですか?

生徒の追加と削除を処理するコードベースの部分から呼び出すことを検討しましたが、同じコンテキストでは問題なく動作しますが、多くの場合、変更は別のバックグラウンド コンテキストで行われます。

このバックグラウンド コンテキストは、View Controller が常に処理する にparentContext設定されているため、保存すると、変更が自動的に にマージされます。の に応じて呼び出しを検討しましたが、呼び出されるまでに、変更は既に行われており、KVO は既にトリガーされています。mainContextmainContextrefreshObject:mergeChanges:NSManagedObjectContextDidSaveNotificationbgContext

以下を追加しようとしましたが、無限ループに陥ります。

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if ([keyPath isEqualToString:@"pupils"])
    {
        [self.school.managedObjectContext refreshObject:self.school mergeChanges:YES];
        self.contentArray = [self.school starPupils];
    }
}

私の現在の実装は次のとおりです。

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if ([keyPath isEqualToString:@"pupils"])
    {
        if (self.contentArray == [self.school starPupils])
        {
            /*
             self.contentArray is currently pointing at previous fetched starPupils
             we need to reset the object to a faulted state
             this will twigger another KVO notification for @"pupils" but the code within this if statement will not be executed again
             */
            [self.school.managedObjectContext refreshObject:self.school mergeChanges:YES];
            self.contentArray = [self.school starPupils];
        }
    }
}

これは機能しますが、最適ではありません。ベストプラクティスへのより良い提案や参照はありますか?

4

1 に答える 1

0

NSManagedObjectContextDidSaveNotificationを使用してUIの更新をトリガーし、KVOをまったく使用しないことは可能でしょうか?

于 2012-10-06T20:31:31.187 に答える