0

Simperium に渡した NSManagedObjectContext から NSManagedObjectContextDidSaveNotification 通知を受け取りません。

基本的に私がやりたいことは、simperium による更新が原因でデータベースの更新が発生したときにアプリケーションに通知することです。

したがって、2 つの NSManagedObjectContext を使用しています。1 つはアプリケーション用、もう 1 つは Simperium 用です。アプリケーションがコンテキストを保存すると、変更は NSManagedObjectContextDidSaveNotification 通知で simperium コンテキストにマージされますmergeChangesFromContextDidSaveNotification:

ただし、問題は、Simperium NSManagedObjectContext が更新されるたびに、NSManagedObjectContextDidSaveNotification を取得できないため、リモートからアプリケーション コンテキストに変更をマージできないことです。実際にデータを永続ストアに保存することを確認しました。

いくつかのコード:

- (void) setSyncingEnabled:(BOOL)syncingEnabled
{
    if (syncingEnabled && !self.simperium)
    {
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(syncingObjectContextDidSaveNotification:)
                                                     name:NSManagedObjectContextDidSaveNotification
                                                   object:self.syncingObjectContext];

        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(objectContextDidSaveNotification:)
                                                     name:NSManagedObjectContextDidSaveNotification
                                                   object:self.objectContext];

        self.simperium = [[Simperium alloc] initWithRootViewController:App.delegate.window.rootViewController];
        self.simperium.authenticationOptional = YES;
        [self.simperium addDelegate:self];

        [self.simperium startWithAppID:kSimperiumAppId
                                APIKey:kSimperiumAPIKey
                                 model:self.objectModel
                               context:self.syncingObjectContext
                           coordinator:self.storeCoordinator];
    }
    else if (self.simperium) {
        self.simperium = nil;

        [[NSNotificationCenter defaultCenter] removeObserver:self name:NSManagedObjectContextDidSaveNotification object:self.syncingObjectContext];
        [[NSNotificationCenter defaultCenter] removeObserver:self name:NSManagedObjectContextDidSaveNotification object:self.objectContext];
    }
}


- (void) objectContextDidSaveNotification:(NSNotification*)notification
{
    if (self.simperium) {
        [self.syncingObjectContext mergeChangesFromContextDidSaveNotification:notification];
    }
}

- (void) syncingObjectContextDidSaveNotification:(NSNotification*)notification
{
    [self.objectContext mergeChangesFromContextDidSaveNotification:notification];

    /* Inform Application */
    [[NSNotificationCenter defaultCenter] postNotificationName:DatabaseDidUpdateExternallyNotification object:self];
}
4

2 に答える 2

1

もう少し掘り下げてみると、Simperium SDKは、指定されたオブジェクトコンテキストではなく、プライベートに作成された別のオブジェクトコンテキストを使用していることがわかりました。そのため、指定したコンテキストは保存されません。現在、プライベート並行コンテキストに到達するためのパブリックAPIはありません。

NSFetchedResultsControllerを使用したくない場合は、多くのオブジェクトを同期し、パフォーマンスがそれほど高くないため、UIの更新を処理するために、オブジェクトが更新された後に1つの通知を送信することもできます。

次のコードは機能しているようです(マスターブランチ):

-(void)objectKeysChanged:(NSSet *)keyArray entityName:(NSString *)entityName
{
    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(informAppAboutExternalChange) object:nil];
    [self performSelector:@selector(informAppAboutExternalChange) withObject:nil afterDelay:0.5];
}

- (void) informAppAboutExternalChange
{
    [[NSNotificationCenter defaultCenter] postNotificationName:kObjectsDidChangeExternallyNotification object:nil];
}

UIを更新する必要がある場合は、通知を確認するだけです。実行が遅れると、通知が頻繁にトリガーされるのを防ぐことができます。これにより、パフォーマンスも低下します。

于 2012-08-15T19:18:29.130 に答える
0

Simperiumを介して更新が行われたときにアプリに通知することが目標であるため、別のコンテキストを使用するよりも優れたオプションがあります(Simperiumはとにかく内部で行います)。

1)NSFetchedResultsControllerオブジェクトの挿入、変更、および削除時に呼び出されるを使用できます。

2)SimperiumDelegate特定の変更に対応するために使用できます。これは、GitHubの「iosupdate」ブランチで現在テストされているリリースでは少し異なります。SimperiumDelegateプロトコルはに置き換えられ、気SPBucketDelegateになる通知をより細かく制御できるようになります。

何らかの理由で本当に2番目のコンテキストを使用する必要がある場合は、ユースケースについてもう少しお話しできるようにご連絡ください。

于 2012-08-14T19:43:24.507 に答える