应用程序在 Nsdata 持久存储调用上崩溃
Posted
技术标签:
【中文标题】应用程序在 Nsdata 持久存储调用上崩溃【英文标题】:App crashes on Nsdata persistent storage call 【发布时间】:2014-01-16 13:08:41 【问题描述】:当应用程序从后台恢复到活动状态时,我有一个调用 NSfetch request
的方法。有时由于NsnotificationManager
,有2个该方法的实例被调用。
当我查看我的应用程序崩溃日志时,它会显示此内容
2 CoreData 0x30321a90 -[_PFLock lock] + 20
3 CoreData 0x30332b34 -[NSPersistentStoreCoordinator executeRequest:withContext:error:] + 776
4 CoreData 0x30331776 -[NSManagedObjectContext executeFetchRequest:error:] + 610
5 My app 0x000ee7e0 -[ViewController CheckExistingData] (ViewController.m:350)
第 350 行的语句是:
NSArray *array = [[self managedObjectContext] executeFetchRequest:fetch error:&error];
这种情况偶尔发生,而且很少没有任何固定的重现步骤。当我检查日志时,这通常发生在同时调用此方法 2 次时;一位来自NSnotification
Manager 和一位来自View 确实出现了。我尝试将@syncronided()
添加到被调用两次的方法中,但我遇到了同样的错误。有没有其他方法可以确保NSfetch
被一个线程访问/比如添加锁之类的。
我们将不胜感激。
【问题讨论】:
您需要使用@synchronized 发布您的一些代码,然后才能有人提供帮助。 【参考方案1】:您可能违反了 Core Data 并发规则。
如果您的上下文是旧的线程限制类型,您需要确保始终从一个线程或串行队列访问它。
如果您的上下文是主队列并发类型,您需要确保从主队列或通过调用-performBlock...:
方法之一来使用它。
如果您的上下文是私有队列并发类型,您必须通过-performBlock...:
方法之一使用它。
这里有一些例子。
线程限制
如果你创建这样的上下文:
NSManagedObjectContext *context = [[NSManagedObjectContext alloc] init];
或者:
NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSConfinementConcurrencyType];
您只能从一个线程或串行队列(创建它的位置)使用此上下文(以及您从中获得的所有托管对象)。
私有队列并发
NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
您只能通过特殊方法 -performBlock:
和 -performBlockAndWait:
使用此上下文及其托管对象:
[context performBlock:^
// Assume error and request exist.
NSArray *objects = [context executeFetchRequest:request error:&error];
];
主队列并发类型
NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
与私有队列并发类型相同。但是因为使用了主队列,所以在主队列上你可以直接使用上下文,而无需将调用包装到-performBlock...:
方法中。
【讨论】:
已更新示例。以上是关于应用程序在 Nsdata 持久存储调用上崩溃的主要内容,如果未能解决你的问题,请参考以下文章
Spring Batch/Data JPA 应用程序在调用 JPA 存储库(save、saveAll)方法时不会将数据持久化/保存到 Postgres 数据库