2010-12-17 99 views
7

alt text使用多线程核心数据应用程序设计的帮助

上面是对我的模型的简化。我的应用程序有一个NSWindowController对象控制用户帐户实体的两个NSViewController对象。当用户登录到应用程序时,他们可以通过调出相关的视图控制器来修改用户或帐户信息。在后台,我有应用程序定期将用户的日志填充到单独线程上的应用程序委托中。

我使用单独的NSManagedObjectContext作为后台线程和应用程序委托的NSManagedObjectContext用于视图控制器中的数据输入。我想知道几件事情:

1)这是一个很好的做法吗?我应该为每个视图控制器创建一个NSManagedObjectContext,然后在用户完成更改时合并上下文吗?

2)因为log实体是在后台线程中创建的,所以它有它自己的NSManagedObjectContext。但是,每个日志包括来自用户帐户实体的信息,这些信息是在应用程序代理的NSManagedObjectContext中创建的。这是怎么了获取用户:

- (NSManagedObjectID*) fetchUser:(NSString*) userID { 
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"user":inManagedObjectContext:self.managedObjectContext]; 
    /** snip **/ 
} 

此方法由后台线程调用如下:

NSManagedObjectID* userObjectID = [self fetchUser:userID]; 
NSManagedObject* userObject = [self.logsManagedObjectContext objectWithID:userObjectID]; 

是我在fetchUser线程安全的我在做什么?如果其中一个视图正在修改同一用户,那么在获取用户时是否需要锁定主管理对象上下文?从this article我了解(也许不正确),我可能必须这样做。到目前为止,我没有遇到任何问题,但我不想留下潜在的优势案例。

3)当视图控制器之一,使更改应用程序委托的NSManagedObjectContext其职位,被处理的通知如下:

- (void)contextDidSave:(NSNotification *)notification { 
    SEL selector = @selector(mergeChangesFromContextDidSaveNotification:); 
    [self.logManagedObectContext performSelector:selector onThread:backgroundThread withObject:notification waitUntilDone:NO]; 
} 

这是我应该如何处理合并或者我应该合并应用程序代理的NSManagedObjectContext而不是?我发现这样做(在主线程上)锁定了用户界面。

任何帮助将不胜感激。

回答

9

NSManagedObjectContext对象不是线程安全的。这意味着如果您希望从多个线程访问Core Data,则每个线程都需要一个线程(并且也在该线程上创建)。其中每个可以使用相同的NSPersistentStoreCoordinator,这将串行化访问持久性存储。

这是因为每个NSManagedObjectContext知道如何正确地锁定NSPersistentStoreCoordinator当它在使用中,避免碰撞。遵循这些规则,您应该保持线程安全。

正如您已经在做的那样,应该使用NSManagedObjectID对象将Core Data对象从一个MOC传递到另一个(以及从一个线程到另一个线程的扩展)。但是,您正在调用fetchUser:,它使用主线程中的MOC,在后台使用。这是不正确的。必须从主线程调用fetchUser:方法调用。当然,没有什么可以阻止你使用后台MOC在后台线程中检索用户。

总之,总是从它在创建线程的NSManagedObjectContext电话。

这里的关键是要确保两个MOCS知道对方的保存,所以你必须注册才能收到通知每个环境。然后您应该从MOC的相应线程执行mergeChangesFromContextDidSaveNotification:。目前,您的后台上下文会被通知主线程上下文的变化,但反之亦然。

哦,并且没有必要为每个NSViewController有一个单独的上下文。作为UI元素,它们与上下文的交互将发生在同一个(主)线程上,因此共享没有问题。

+0

我不知道我可以从后台MOC中检索用户。我需要做的就是给他们相同的** NSPersistentStoreCoordinator **?如果我这样做,我需要检索使用对象ID或我可以直接获取对象? – David 2010-12-23 23:33:25

+0

您可以直接获取对象。只要确保编写代码以合并来自共享相同协调器的其他MOC的通知时的更改。 – paulbailey 2010-12-30 11:04:10