我的应用程序有时会在完全加载到以下行之前崩溃:
if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error])
这个if状态所在的完整方法如下(我认为这是非常标准的):
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (__persistentStoreCoordinator != nil) {
return __persistentStoreCoordinator;
}
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"CoreData.sqlite"];
NSError *error = nil;
__persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
return __persistentStoreCoordinator;
}
更新
第二次调用-(NSPersistentStoreCoordinator *)persistentStoreCoordinator
方法时发生崩溃。的修改
从第一个可见的viewController调用它的第一个时间:
- (void)updateStats {
NSLog(@"Updating stats");
dispatch_queue_t request_queue = dispatch_queue_create("updateNumberOfSchedules", NULL);
dispatch_async(request_queue, ^{
AppDelegate *theDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [[NSManagedObjectContext alloc] init];
[context setPersistentStoreCoordinator:[theDelegate persistentStoreCoordinator]];
...
});
}
第二次(当我的DeviceLinker类要在checkInactiveLinks方法中检查数据库中的非活动链接时,有时会发生崩溃。在applicationDidBecomeActive
启动时调用此方法:
-(void) checkInactiveLinks {
AppDelegate *theDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSManagedObjectContext *newMoc = [[NSManagedObjectContext alloc] init];
[newMoc setPersistentStoreCoordinator:[theDelegate persistentStoreCoordinator]];
...
}
纠正我如果我错了但是读了我的代码我会认为第二次调用persistentStoreCoordinator getter它应该返回__persistentStoreCoordinator而不分配并初始化一个新的...
更新2 在if语句的同一行上我也经常得到这个:
-[__NSCFDictionary _hasPrecomputedKeyOrder]: unrecognized selector sent to instance 0x7dd3770
更新3
我编辑了我的构建方案,并在诊断选项卡下启用了僵尸和日志异常。现在我看到-[NSPersistentStoreCoordinator unlock]: message sent to deallocated instance 0x8916090
。请注意,我的代码中没有任何显式锁定。
答案 0 :(得分:19)
看起来您正在同时从多个线程进入该段代码。当你进行延迟实例化时,你必须确保只通过一个执行线程的“第一次”将同时通过。您可以使用以下策略在主线程上同步对它的访问。
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (__persistentStoreCoordinator != nil) {
return __persistentStoreCoordinator;
}
// Add this block of code. Basically, it forces all threads that reach this
// code to be processed in an ordered manner on the main thread. The first
// one will initialize the data, and the rest will just return with that
// data. However, it ensures the creation is not attempted multiple times.
if (![NSThread currentThread].isMainThread) {
dispatch_sync(dispatch_get_main_queue(), ^{
(void)[self persistentStoreCoordinator];
});
return __persistentStoreCoordinator;
}
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"CoreData.sqlite"];
NSError *error = nil;
__persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
return __persistentStoreCoordinator;
}
答案 1 :(得分:1)
我正在使用GCD来使用线程。
和
我的应用程序有时会在完全加载之前崩溃 以下一行:
听起来像并发相关错误的经典症状;间歇性的,似乎在错误的地方。
CoreData非常specific concurrency requirements。你在见面吗?
答案 2 :(得分:1)
我更喜欢自旋锁,它比在主线程中递归调用getter方法更清晰。 这是我的解决方案:
#import <libkern/OSAtomic.h>
@implementation MyClass {
OSSpinLock _lock;
}
- (instancetype)init {
self = [super init];
if (self){
_lock = OS_SPINLOCK_INIT;
}
}
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (__persistentStoreCoordinator != nil) {
return __persistentStoreCoordinator;
}
// Lock the current thread
OSSpinLockLock(&_lock);
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"CoreData.sqlite"];
NSError *error = nil;
__persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
// Unlock
OSSpinLockUnlock(&_lock);
return __persistentStoreCoordinator;
}
答案 3 :(得分:0)
我认为当您添加新的持久性存储时,您应首先锁定持久性存储协调器,以便它不会干扰其他持久性存储。
在下面的代码中,psc
是对新创建的持久性存储协调器的单独引用。如果我正确理解你的目的,那么方法的这一部分应该是dispatch_async
ed。
[psc lock];
if (![__persistentStoreCoordinator
addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:storeURL
options:nil error:&error]) {
// deal with the error
}
[psc unlock];