NSManagedObjectContextDidSaveNotification和Simperium

时间:2012-08-14 15:25:02

标签: simperium

我没有从我给Simperium的NSManagedObjectContext获取NSManagedObjectContextDidSaveNotification通知。

基本上我喜欢做的是在由于更新simperium而发生数据库更新时通知我的应用程序。

因此我使用2个NSManagedObjectContexts,一个用于我的应用程序,另一个用于Simperium。一旦我的应用程序保存其上下文,更改将通过mergeChangesFromContextDidSaveNotification:合并到NSManagedObjectContextDidSaveNotification通知中的simperium上下文。

然而问题是,只要有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];
}

2 个答案:

答案 0 :(得分:1)

我深入挖掘并发现Simperium SDK没有使用您提供的对象上下文,而是另一个私有创建的对象上下文。这就是为什么你给它的上下文永远不会被保存的原因。目前没有公共API可以访问私有并发上下文。

如果您不想使用NSFetchedResultsController,因为您同步了很多对象并且性能不是很好,您还可以在更新对象后处理一个通知,以处理更新UI。

以下代码似乎有用(主分支):

-(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的地方观察通知即可。延迟执行还应该防止过于频繁地触发通知,这也会降低性能。

答案 1 :(得分:0)

由于您的目标是在通过Simperium发生更新时通知您的应用,因此有更好的选择,而不是使用单独的上下文(无论如何Simperium在内部执行):

1)您可以使用NSFetchedResultsController,当插入,更改和删除对象时,将调用SimperiumDelegate

2)您可以使用SimperiumDelegate对特定更改做出反应。这在当前正在GitHub上的“iosupdate”分支中测试的版本中有所不同。 SPBucketDelegate协议将替换为{{1}},以便您更好地控制您关注的通知。

如果由于某种原因你确实需要使用第二个上下文,请get in touch,以便我们再谈谈你的用例。