1

我手上有一个难题。

我在 xcode 中对我的 SQLite 数据库执行NSFetchRequest,我正在运行的查询非常简单:

NSFetchRequest *request = [[NSFetchRequest alloc] init];
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [appDelegate managedObjectContext];
[[context undoManager] disableUndoRegistration];
NSError *error = nil;
NSEntityDescription *entity = nil;

entity = [NSEntityDescription entityForName:@"Workbook" inManagedObjectContext:context];

[request setEntity:entity];
[request setPredicate:[NSPredicate predicateWithFormat:@"language == 'English'" ]];
[request setSortDescriptors:[NSArray arrayWithObject:[[NSSortDescriptor alloc]initWithKey:@"sequence" ascending:YES]]];

NSLog(@"----- Request Print out: %@",request);
NSArray *subjects = [context executeFetchRequest:request error:&error];

此代码第一次工作时执行良好。

然后我更改我的视图并在应用程序的不同部分执行另一个提取和插入导航回托管此代码的视图,然后代码无法执行:

[context executeFetchRequest:request error:&error];

该应用程序不会冻结或崩溃,并且控制台上不会显示任何错误消息。我什至为我的 sql db 提取启用了日志记录,我可以看到请求的 sql 从未第二次执行。

记录时的获取请求如下所示:

<NSFetchRequest: 0x20063120> (entity: Workbook; predicate: (language == "English"); sortDescriptors: (("(sequence, ascending, compare:)")); type: NSManagedObjectResultType; )

这与代码第一次执行和第二次执行时相同,因此请求本身不会成为问题。

在之前的操作之后,我的数据库是否有可能被锁定?

应用程序是否会失去与数据库的连接,因为数据库没有收到请求?

我已经离开了应用程序,看看是否有任何事情发生,但它只是无限期地坐着......

我已经尝试了所有我能想到的分析等,但找不到任何明显的东西,比如泄漏或发生奇怪的过程。

所有帮助表示赞赏

4

1 回答 1

0

从您提供的链接并查看MBProgressHUD源代码,很明显您正在从不同的线程访问您的上下文,然后是创建它的线程(线程限制违规),而不是使用私有队列上下文。

进度HUD正在为选择器执行分离一个新线程,而您的上下文可能被定义为“限制”或“主线程”并发。

第一次,上下文是在分离线程 (T1) 上创建的,当您再次返回视图控制器时,它会在另一个分离线程 (T2) 上使用。

因为我真的不知道MBProgressHUD,所以我给你的建议是找到一种方法来执行你在主线程上调用的选择器,而进度 HUD 正在做它的事情。
或者,在临时上下文(将在分离线程中创建并在分离线程上处理的上下文)上执行此加载,然后将结果导出到主上下文/线程。

CoreData 不允许在线程之间传递托管对象或托管上下文

快速解决方法是:(
此解决方案将数据作为字典导入临时受限上下文中)

NSFetchRequest *request = [[NSFetchRequest alloc] init];
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSConfinementConcurrencyType];
context.persistentStoreCoordinator = appDelegate.persistentStoreCoordinator;
context.undoManager = nil;
NSError *error = nil;
NSEntityDescription *entity = nil;

entity = [NSEntityDescription entityForName:@"Workbook" inManagedObjectContext:context];

[request setEntity:entity];
[request setPredicate:[NSPredicate predicateWithFormat:@"language == 'English'" ]];
[request setSortDescriptors:[NSArray arrayWithObject:[[NSSortDescriptor     alloc]initWithKey:@"sequence" ascending:YES]]];
[request setResultType:NSDictionaryResultType];
[request setPropertiesToFetch:@[/*the properties you need*/]];

NSLog(@"----- Request Print out: %@",request);
NSArray *subjects = [context executeFetchRequest:request error:&error];
//you can now pass subjects between thread as it contains 
//dictionaries and not managed objects
于 2013-09-20T10:07:27.060 回答