0

我没有从我提供给 Simperium 的 NSManagedObjectContext 收到 NSManagedObjectContextDidSaveNotification 通知。

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

因此,我使用 2 个 NSManagedObjectContexts,一个用于我的应用程序,另一个用于 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。

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

-(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为让您更好地控制您关心的通知。

如果出于某种原因您确实需要使用第二个上下文,请与我们联系,以便我们进一步讨论您的用例。

于 2012-08-14T19:43:24.507 回答