iOS多线程核心数据应用程序未合并更改

时间:2012-11-22 10:31:50

标签: ios core-data nsmanagedobject nsmanagedobjectcontext nsoperation

我有一个iOS应用程序,它从两个线程访问核心数据sql数据库。线程A(主UI线程)更新核心数据记录,然后线程B尝试从线程A刚刚更新的实体集合中读取。麻烦的是,线程B没有“看到”线程A持续存在的变化。

通过将NSOperation子类对象添加到NSOperationQueue来创建线程B. NSOperation子类的主要方法如下:

-(void) main {

    // NEED to create the MOC here and pass to the methods.
    NSManagedObjectContext* moc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSConfinementConcurrencyType];

    [moc setUndoManager:nil];

    [moc setMergePolicy:NSMergeByPropertyStoreTrumpMergePolicy]; // Had been working for months 

    [moc setPersistentStoreCoordinator:getApp().persistentStoreCoordinator];

    [self doTheWorkWithMOC:moc]; // Actually performs updates, using moc


    moc = nil;



}

稍后,线程B保存其更改,如下所示:

@try {
                // register for the moc save notification - this is so that other MOCs can be told to merge the changes
                [[NSNotificationCenter defaultCenter] 
                 addObserver:getApp() 
                 selector:@selector(handleDidSaveNotification:)
                 name:NSManagedObjectContextDidSaveNotification 
                 object:moc];

                NSError* error = nil;
                if ([moc save:&error] == YES)
                {
                    NSLog(@"%s SAVED FINE",__FUNCTION__);

                }else {
                    NSLog(@"%s NOT saved, error=%@ %@",__FUNCTION__,error,[error localizedDescription]);

                }

                // unregister from notification
                [[NSNotificationCenter defaultCenter] 
                 removeObserver:getApp() 
                 name:NSManagedObjectContextDidSaveNotification 
                 object:moc];





            }
            @catch (NSException * e) {
                NSLog(@"%s Exception: %@",__FUNCTION__, e);

            }

主UI appdelegate包含以下代码来处理保存通知:

- (void)handleDidSaveNotification:(NSNotification*) note 
{

    @try {

        // Notifications run on the same thread as the notification caller.
        // However, we need to ensure that any db merges run on the main ui thread.
        // Hence:
        [self performSelectorOnMainThread:@selector(mergeContexts:) withObject:note waitUntilDone:NO]; 


    }
    @catch (NSException * e) {
        NSLog(@"appDelegate handleDidSaveNotification Exception: %@", e);
    }

}
-(void)mergeContexts:(NSNotification*) note 
{
    if ([__managedObjectContext tryLock]==YES)
    {
        [__managedObjectContext mergeChangesFromContextDidSaveNotification:note];

        [__managedObjectContext unlock];
    }

}

大多数时候一切正常。

但是,我有一台iPad,当线程A读取数据库时,未检测到线程B写入的更改。

任何人都可以在我的代码中看到任何导致这种情况的内容吗?

非常感谢

1 个答案:

答案 0 :(得分:0)

熟练工,

首先,您应该转向使用iOS v5和Lion中引入的基于队列的MOC。这样可以更容易地使两个MOC保持同步。您将不再需要使用锁定系统。

其次,一旦你转移到排队的MOC,那么为了响应“保存”通知,让它们保持同步是非常简单的。

第三,为什么总是添加和删除已保存通知的观察者?这看起来不是很可疑吗?很明显,你错过了MOC之间的一些更新。

安德鲁