managedObjectModel 为 nil(仅在 WatchApp 中)
managedObjectModel in nil ( only in WatchApp )
我正在为 Apple Watch 更新应用程序
这个应用程序使用 coredata ,所以我创建了一个框架来管理核心数据堆栈!
当我在设备或模拟器上运行该应用程序时,该应用程序工作正常,但是当我在 Apple Watch 模拟器上运行它时,该应用程序崩溃并显示此日志
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Cannot create an
NSPersistentStoreCoordinator with a nil model'
问题似乎出在 managedObjectModel 上,如果我记录它
NSLog(@"managedObjectModel %@", _managedObjectModel);
日志返回
managedObjectModel (null)
框架中的代码似乎是正确的,实际上主应用程序运行完美
反正这是框架的内容
#import "DataAccess.h"
@implementation DataAccess
@synthesize managedObjectContext = _managedObjectContext;
@synthesize managedObjectModel = _managedObjectModel;
@synthesize persistentStoreCoordinator = _persistentStoreCoordinator;
+ (instancetype)sharedInstance
{
static DataAccess *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[DataAccess alloc] init];
// Do any other initialisation stuff here
});
return sharedInstance;
}
- (void)saveContext
{
NSError *error = nil;
NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
if (managedObjectContext != nil) {
if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
}
}
#pragma mark - Core Data stack
// Returns the managed object context for the application.
// If the context doesn't already exist, it is created and bound to the persistent store coordinator for the application.
- (NSManagedObjectContext *)managedObjectContext
{
if (_managedObjectContext != nil) {
return _managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
_managedObjectContext = [[NSManagedObjectContext alloc] init];
[_managedObjectContext setPersistentStoreCoordinator:coordinator];
}
return _managedObjectContext;
}
// Returns the managed object model for the application.
// If the model doesn't already exist, it is created from the application's model.
- (NSManagedObjectModel *)managedObjectModel
{
if (_managedObjectModel != nil) {
NSLog(@"managedObjectModel %@", _managedObjectModel);
return _managedObjectModel;
}
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"MyApp" withExtension:@"momd"];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
NSLog(@"managedObjectModel %@", _managedObjectModel);
return _managedObjectModel;
}
// Returns the persistent store coordinator for the application.
// If the coordinator doesn't already exist, it is created and the application's store added to it.
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (_persistentStoreCoordinator != nil) {
return _persistentStoreCoordinator;
}
//NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"TMM.sqlite"];
//NSURL *storeURL = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSAllDomainsMask] lastObject];
// storeURL = [storeURL URLByAppendingPathComponent:@"db.sqlite"];
NSURL *storeURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.ragazzetto.MyApp.Documents"];
storeURL = [storeURL URLByAppendingPathComponent:@"MyApp.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;
}
#pragma mark - Application's Documents directory
// Returns the URL to the application's Documents directory.
- (NSURL *)applicationDocumentsDirectory
{
return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}
@end
问题出在哪里?
感谢您的帮助
当您编写 iOS 应用程序扩展时——包括所有当前的 WatchKit 应用程序——您正在创建一个单独的可执行文件,它有自己的包。应用中的资源不一定在扩展中可用,反之亦然。所以当你这样做时:
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"MyApp" withExtension:@"momd"];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
当 运行 在 WatchKit 应用程序中时,URL 与在包含应用程序中的 运行 不同。该错误告诉您 WatchKit 应用程序的 URL 无效,即 WatchKit 应用程序的捆绑包中没有模型文件。
简单的解决方法是将模型包含在 WatchKit 包中。通过以下方式执行此操作:
- 选择Xcode中的模型文件
- 正在打开 Xcode window
右侧的文件检查器面板
- 查看 "target membership" 部分。确保选择了您的 WatchKit 目标。
这应该可行,但意味着您有模型文件的两个副本。更好的方法是将模型文件放入两个目标都使用的共享框架中。这有点复杂,但稍微搜索一下就会找到详细的步骤。
我正在为 Apple Watch 更新应用程序 这个应用程序使用 coredata ,所以我创建了一个框架来管理核心数据堆栈! 当我在设备或模拟器上运行该应用程序时,该应用程序工作正常,但是当我在 Apple Watch 模拟器上运行它时,该应用程序崩溃并显示此日志
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Cannot create an NSPersistentStoreCoordinator with a nil model'
问题似乎出在 managedObjectModel 上,如果我记录它
NSLog(@"managedObjectModel %@", _managedObjectModel);
日志返回
managedObjectModel (null)
框架中的代码似乎是正确的,实际上主应用程序运行完美
反正这是框架的内容
#import "DataAccess.h"
@implementation DataAccess
@synthesize managedObjectContext = _managedObjectContext;
@synthesize managedObjectModel = _managedObjectModel;
@synthesize persistentStoreCoordinator = _persistentStoreCoordinator;
+ (instancetype)sharedInstance
{
static DataAccess *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[DataAccess alloc] init];
// Do any other initialisation stuff here
});
return sharedInstance;
}
- (void)saveContext
{
NSError *error = nil;
NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
if (managedObjectContext != nil) {
if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
}
}
#pragma mark - Core Data stack
// Returns the managed object context for the application.
// If the context doesn't already exist, it is created and bound to the persistent store coordinator for the application.
- (NSManagedObjectContext *)managedObjectContext
{
if (_managedObjectContext != nil) {
return _managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
_managedObjectContext = [[NSManagedObjectContext alloc] init];
[_managedObjectContext setPersistentStoreCoordinator:coordinator];
}
return _managedObjectContext;
}
// Returns the managed object model for the application.
// If the model doesn't already exist, it is created from the application's model.
- (NSManagedObjectModel *)managedObjectModel
{
if (_managedObjectModel != nil) {
NSLog(@"managedObjectModel %@", _managedObjectModel);
return _managedObjectModel;
}
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"MyApp" withExtension:@"momd"];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
NSLog(@"managedObjectModel %@", _managedObjectModel);
return _managedObjectModel;
}
// Returns the persistent store coordinator for the application.
// If the coordinator doesn't already exist, it is created and the application's store added to it.
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (_persistentStoreCoordinator != nil) {
return _persistentStoreCoordinator;
}
//NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"TMM.sqlite"];
//NSURL *storeURL = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSAllDomainsMask] lastObject];
// storeURL = [storeURL URLByAppendingPathComponent:@"db.sqlite"];
NSURL *storeURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.ragazzetto.MyApp.Documents"];
storeURL = [storeURL URLByAppendingPathComponent:@"MyApp.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;
}
#pragma mark - Application's Documents directory
// Returns the URL to the application's Documents directory.
- (NSURL *)applicationDocumentsDirectory
{
return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}
@end
问题出在哪里?
感谢您的帮助
当您编写 iOS 应用程序扩展时——包括所有当前的 WatchKit 应用程序——您正在创建一个单独的可执行文件,它有自己的包。应用中的资源不一定在扩展中可用,反之亦然。所以当你这样做时:
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"MyApp" withExtension:@"momd"];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
当 运行 在 WatchKit 应用程序中时,URL 与在包含应用程序中的 运行 不同。该错误告诉您 WatchKit 应用程序的 URL 无效,即 WatchKit 应用程序的捆绑包中没有模型文件。
简单的解决方法是将模型包含在 WatchKit 包中。通过以下方式执行此操作:
- 选择Xcode中的模型文件
- 正在打开 Xcode window 右侧的文件检查器面板
- 查看 "target membership" 部分。确保选择了您的 WatchKit 目标。
这应该可行,但意味着您有模型文件的两个副本。更好的方法是将模型文件放入两个目标都使用的共享框架中。这有点复杂,但稍微搜索一下就会找到详细的步骤。