我的手上有一点难题。
我正在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 fetches启用了日志记录,我可以看到请求的sql从未在第二次执行。
记录时的提取请求如下所示:
<NSFetchRequest: 0x20063120> (entity: Workbook; predicate: (language == "English"); sortDescriptors: (("(sequence, ascending, compare:)")); type: NSManagedObjectResultType; )
这与代码第一次执行时以及执行第二次代码时相同,因此请求本身不是问题。
在我之前的操作之后,我的数据库是否有可能被锁定?
应用程序是否会松散与数据库的连接,因为数据库没有收到请求?
我已离开应用程序,看看是否有任何事情发生但它只是无限期地停留......
我已经尝试了所有可以想到的分析等,但找不到任何明显的泄漏或奇怪的过程。
所有帮助表示赞赏
答案 0 :(得分:0)
从您提供的链接,并查看MBProgressHUD
源,很明显您从不同的线程访问您的上下文,然后是它创建的(线程限制违规)而不使用私有队列上下文点。
进度HUD为选择器执行分配新线程,而您的上下文可能被定义为“confinment”或“主线程”并发。
第一次,在分离的线程(T1)上创建上下文,当您再次返回到视图控制器时,它将在另一个分离的线程(T2)上使用。
由于我真的不知道MBProgressHUD
,我的建议是找到一个方法来执行你在主线程上调用的选择器,同时进度HUD正在做它的事情。
或者,在临时上下文(将在分离的线程中创建并放置在ditached线程上)上执行此加载,然后将结果导出到主上下文/线程。
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