为什么我不能使用此代码从委托中获取上下文?

时间:2010-08-28 12:24:35

标签: iphone objective-c nsmanagedobject nsmanagedobjectcontext

我从以下代码中得到了一个令人烦恼的模糊错误:

GFree2AppDelegate *delegate = [[UIApplication sharedApplication] delegate];
context = [delegate managedObjectContext];

context在.h文件中定义为NSManagedObjectContext,在委托中相同。似乎包含了所有正确的文件(除了.m文件中的<CoreData/CoreData.h> - 但程序是否会引发相同的问题,无论它是否包括在内。它包含在头文件中。)

包含所有正确的框架和内容 - 当我开始项目时,我选择“使用coredata来管理数据”或其他任何内容。那肯定不应该有问题吗?

有没有更好的方法来做我想做的事情?基本上我不想继续通过不同的类传递上下文,直到我最终想要使用它(存储数据是我的应用程序的一小部分)。

在控制台中我得到的错误是:

    2010-08-28 13:09:24.726 GFree2[3912:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSURL initFileURLWithPath:]: nil string parameter'
...

    terminate called after throwing an instance of 'NSException'
    Program received signal:  “SIGABRT”.

如果我注释掉这一行:context = [delegate managedObjectContext];那么一切似乎都运转正常。 (目前我还没有实际使用任何coredata或其他任何东西,所以没有更多的代码与它相关。

感谢所有能够提供帮助或对此提供一些见解的人 - 非常复杂。

编辑:我的app委托文件方法:

#pragma mark -
#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) {
    return managedObjectModel;
  }

  NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"GFree" ofType:@"momd"];
  NSURL *modelURL = [NSURL fileURLWithPath:modelPath];
  managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];    
  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 = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent: @"GFree.sqlite"]];

  NSError *error = nil;
  persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
  if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&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. If it is not possible to recover from the error, display an alert panel that instructs the user to quit the application by pressing the Home button.

      Typical reasons for an error here include:
        * The persistent store is not accessible;
        * The schema for the persistent store is incompatible with current managed object model.

      Check the error message to determine what the actual problem was.

      If the persistent store is not accessible, there is typically something wrong with the file path. Often, a file URL is pointing into the application's resources directory instead of a writeable directory.

      If you encounter schema incompatibility errors during development, you can reduce their frequency by:
        * Simply deleting the existing store:
          [[NSFileManager defaultManager] removeItemAtURL:storeURL error:nil]

        * Performing automatic lightweight migration by passing the following dictionary as the options parameter: 
          [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES],NSMigratePersistentStoresAutomaticallyOption, [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];

        Lightweight migration will only work for a limited set of schema changes; consult "Core Data Model Versioning and Data Migration Programming Guide" for details.

    */
    NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
    abort();
  }    

  return persistentStoreCoordinator;
}

#pragma mark -
#pragma mark Application's Documents directory

/**
 Returns the path to the application's Documents directory.
 */
- (NSString *)applicationDocumentsDirectory {
  return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
}

再次编辑:

NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"GFree" ofType:@"momd"];
    NSURL *modelURL = [NSURL fileURLWithPath:modelPath];

是错误所在的行。我不确定这是什么类型的文件,但我确定它显然没有找到它或什么......:/任何想法我应该做什么?

@kiamlaluno - 抱歉回滚你的编辑,并不是故意的,只是好奇地看到你改变了什么,并认为这会告诉我......但它显然完全删除了它们。洛尔。

修改构建结果:

DataModelCompile build/Debug-iphonesimulator/GFree2.app/GFree2.mom GFree2.xcdatamodel
cd "/Volumes/files/Gluten Free Cooking/Tom iPhone App/GFree2"
setenv PATH "/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin:/Developer/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin"
/Developer/usr/bin/momc -XD_MOMC_TARGET_VERSION=10.6 "/Volumes/files/Gluten Free Cooking/Tom iPhone App/GFree2/GFree2.xcdatamodel" "/Volumes/files/Gluten Free Cooking/Tom iPhone App/GFree2/build/Debug-iphonesimulator/GFree2.app/GFree2.mom"

2 个答案:

答案 0 :(得分:1)

我认为问题出在persistentStoreCoordinator文件的GFree2AppDelegate.m方法中。

您是否可以使用此文件中的managedObjectModelmanagedObjectContextpersistentStoreCoordinator方法的确切代码更新您的问题?

当您选中“使用核心数据进行存储”时,这些方法由XCode生成。

顺便说一句,你不应该导入.m文件。

答案 1 :(得分:1)

您收到错误是因为GFree.momd不存在。来自NSURL的pathForResource:ofType:方法:

的文档

返回值资源文件的完整路径名,如果无法找到该文件,则为nil。

GFree.momd是在构建时从.xcdatamodeld文件生成的(在Build Results中查看启动DataModelVersionCompile的行并展开它)。您是否删除或重命名了该文件?

它是否仍然列在构建目标的“编译源”部分中? (在Xcode中展开Targets / [AppName] / Compile Sources)。

注意到您的调试日志表明该应用程序名为GFree2,但您的代码正在寻找GFree.momd。你重命名了这个项目吗?如果数据模型文件现在名为GFree2.xcdatamodeld,那么您需要更改导入momd文件的行以使用新的GFree2名称。