gpt4 book ai didi

iphone - 多线程应用程序中 NSManagedObjectContext 的通用方法

转载 作者:太空狗 更新时间:2023-10-30 03:20:42 25 4
gpt4 key购买 nike

我在这里阅读了很多关于 NSManagedObjectContext 和多线程应用程序的文章。我还查看了 CoreDataBooks 示例,以了解单独的线程如何需要它们自己的 NSManagedObjectContext,以及保存操作如何与主 NSManagedObjectContext 合并。我发现这个例子很好,但也太具体了。我试图概括这一点,并想知道我的方法是否合理。

我的方法是使用一个通用函数来获取当前线程的 NSManagedObjectContext。该函数返回主线程的 NSManagedObjectContext,但如果从不同的线程中调用,它将创建一个新的(或从缓存中获取它)。过程如下:

+(NSManagedObjectContext *)managedObjectContext {
MyAppDelegate *delegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
NSManagedObjectContext *moc = delegate.managedObjectContext;

NSThread *thread = [NSThread currentThread];

if ([thread isMainThread]) {
return moc;
}

// a key to cache the context for the given thread
NSString *threadKey = [NSString stringWithFormat:@"%p", thread];

// delegate.managedObjectContexts is a mutable dictionary in the app delegate
NSMutableDictionary *managedObjectContexts = delegate.managedObjectContexts;

if ( [managedObjectContexts objectForKey:threadKey] == nil ) {
// create a context for this thread
NSManagedObjectContext *threadContext = [[[NSManagedObjectContext alloc] init] autorelease];
[threadContext setPersistentStoreCoordinator:[moc persistentStoreCoordinator]];
// cache the context for this thread
[managedObjectContexts setObject:threadContext forKey:threadKey];
}

return [managedObjectContexts objectForKey:threadKey];
}

如果从主线程调用,保存操作很简单。从其他线程调用的保存操作需要在主线程中合并。为此,我有一个通用的 commit 函数:

+(void)commit {
// get the moc for this thread
NSManagedObjectContext *moc = [self managedObjectContext];

NSThread *thread = [NSThread currentThread];

if ([thread isMainThread] == NO) {
// only observe notifications other than the main thread
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(contextDidSave:)
name:NSManagedObjectContextDidSaveNotification
object:moc];
}

NSError *error;
if (![moc save:&error]) {
// fail
}

if ([thread isMainThread] == NO) {
[[NSNotificationCenter defaultCenter] removeObserver:self
name:NSManagedObjectContextDidSaveNotification
object:moc];
}
}

contextDidSave: 函数中,如果 commit 中的通知调用,我们将执行合并。

+(void)contextDidSave:(NSNotification*)saveNotification {
MyAppDelegate *delegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
NSManagedObjectContext *moc = delegate.managedObjectContext;

[moc performSelectorOnMainThread:@selector(mergeChangesFromContextDidSaveNotification:)
withObject:saveNotification
waitUntilDone:YES];
}

最后,我们用这个清理 NSManagedObjectContext 的缓存:

+(void)initialize {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(threadExit)
name:NSThreadWillExitNotification
object:nil];
}

+(void)threadExit {
MyAppDelegate *delegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
NSString *threadKey = [NSString stringWithFormat:@"%p", [NSThread currentThread]];
NSMutableDictionary *managedObjectContexts = delegate.managedObjectContexts;

[managedObjectContexts removeObjectForKey:threadKey];
}

这可以编译并且似乎可以工作,但我知道由于竞争条件,线程问题可能会很棘手。有人认为这种方法有问题吗?

另外,我在异步请求的上下文中使用它(使用 ASIHTTPRequest),它从服务器获取一些数据并更新和插入 iPhone 上的商店。似乎 NSThreadWillExitNotification 在请求完成后不会触发,并且同一线程随后用于后续请求。这意味着相同的 NSManagedObjectContext 用于同一线程上的不同请求。这是个问题吗?

最佳答案

在发布这个问题一年后,我终于构建了一个框架来概括和简化我使用 Core Data 的工作。它超越了最初的问题,并添加了许多功能,使 Core Data 交互变得更加容易。详情在这里:https://github.com/chriscdn/RHManagedObject

关于iphone - 多线程应用程序中 NSManagedObjectContext 的通用方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3474960/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com