0

最近我添加了一些对我的不同域模型(代表持久数据的子集)的并发访问。我的崩溃报告显示我现在偶然发现了 iOS7、iOS8 和 iOS9 上的一些错误,这些错误似乎都是基于

NSSQLiteErrorDomain=26, NSUnderlyingException=File at path 似乎不是我在源代码中标记的位置的 SQLite 数据库

不幸的是,我无法重现它,我也无法想象某些设备上不存在 sqlite 文件,因为我将它与我的应用程序捆绑包一起提供。

  1. 我的代码中是否存在阻止我访问 sqlite 文件的缺陷?
  2. 除了丢失的文件之外,还有其他可能发生此错误的可能性吗?

这是我的模型单例初始化的源代码和NSManagedObjectContext

+ (id) sharedModel {
    static id sharedModel = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^ {
        sharedModel = [[self alloc] initWithStoreURL: kDefaultStoreURL];
    });
    return sharedModel;
}

- (id) initWithStoreURL:(NSURL *)storeURL {
    self = [super init];
    if (self) {
        // create managed object model
        NSURL * modelURL = [[NSBundle mainBundle] URLForResource: @"MyApp" withExtension: @"momd"];
        NSManagedObjectModel *objectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL: modelURL];
        // create persistent store coordinator
        NSError * error = nil;
        NSPersistentStoreCoordinator * storeCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:objectModel];
        if (![storeCoordinator addPersistentStoreWithType: NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
            CLS_LOG(@"Unresolved error %@, %@", error, [error userInfo]); 
            // this is where the error occurs
            abort();
        }
        // init managedObjectContext
        context = [[NSManagedObjectContext alloc] initWithConcurrencyType: NSMainQueueConcurrencyType];
        [context setPersistentStoreCoordinator:storeCoordinator];
        _mainContext = context;

        _someDomainModel1 = [[SomeDomainModel1 alloc] initWithContext:_mainContext];
        _someDomainModel2 = [[SomeDomainModel2 alloc] initWithContext:_mainContext];
    }
    return self;
}
4

1 回答 1

1

initWithStoreURL可能有问题,但如果您一直使用相同的代码,也许我做出了不正确的假设。

您说您的 SQLite 存储文件随捆绑包一起提供,如果是这种情况,您需要以只读方式并以回滚模式打开它。

NSDictionary *storeOptions = @{
    NSReadOnlyPersistentStoreOption:@YES,
    NSSQLitePragmasOption:@{@"journal_mode":@"DELETE"}};

然后,在添加商店时使用选项。

if (![storeCoordinator addPersistentStoreWithType:NSSQLiteStoreType
                                    configuration:nil
                                              URL:storeURL
                                          options:storeOptions
                                            error:&error]) {
}

此外,既然您看到了这一点,您应该记录更多信息(例如 URL 和错误对象的详细信息)。

但是,您正在调用 abort(),因此您也应该能够从崩溃报告中获取堆栈跟踪和状态信息。

另一件事......看看你是如何生成你的数据库的。您还应该确保在回滚模式 (journal_mode=DELETE) 下生成它。

于 2015-11-03T17:25:44.557 回答