views:

205

answers:

2

I get an annoyingly vague error from the following code:

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

context is defined as a NSManagedObjectContext in the .h file and is the same in the delegate. All the right files seem to be included (except for <CoreData/CoreData.h> in the .m file - but the program throws the same issue whether its included or not. Its included in the header file.)

All the correct frameworks and stuff are included - when I started the project I selected "use coredata to manage data" or whatever it was. So surely there shouldn't be a problem?

Is there a better way to do what I'm trying to do? Basically I don't want to have to keep passing the context through different classes till I eventually want to use it (storing data is such a small part of my application).

In the console the error I get is:

    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”.

If I comment out the line: context = [delegate managedObjectContext]; then it all seems to work fine. (at the moment I haven't acctually used any coredata or anything so theres no more code related to it.

Thanks for anyone who can help, or provide some insight into this - its so complicated.

Edit: my app delegate file methods:

#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];
}

EDIT AGAIN:

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

is the line where the error is. I'm not sure what type of file this is, but I'm sure it's obviously not finding it or something... :/ any ideas what I'm supposed to do?

@kiamlaluno - sorry for rolling back your edits, didn't mean to, just curious to see what you'd changed and thought that would show me... but it just completely removed them apparently. lol.

Edit build results:

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"
+1  A: 

I believe that the problem is in persistentStoreCoordinator method in your GFree2AppDelegate.m file.

Could you update your question with the exact code of managedObjectModel, managedObjectContext and persistentStoreCoordinator methods from this file?

These methods are generated by the XCode when you check "Use Core Data for storage".

By the way, you shouldn't import .m files.

Michael Kessler
updated my post. I don't import any .m files... only import .h files - but I'm never sure wether i'm supposed to import files in the .h file or in the .m file. :/ frameworks seem to automatically go in the .h file, so does that mean they don't need to be included in the .m?
Thomas Clayson
You should import as much as possible in the .m files. In most cases you can avoid warnings in .h files by adding the `@class MyClass;` line before the `@interface`... Usually you have to add import in .h files only for classes that you inherit from or declare that your class implements a protocol that is located in some file...
Michael Kessler
Regarding your problem, try padding all the `fileURLWithPath` in the Core Data methods with prints to log (one before and one after) and find which one is the source to the problem...
Michael Kessler
thanks @michael - lots of useful advice there. I used break points and the point at which the application breaks I've put in my original post above. I can't find that file - and I'm not really sure where I should be looking for it/whether it actually exists. hmm...
Thomas Clayson
This file is you app delegate - the `managedObjectModel` method...
Michael Kessler
I got rid of the persistentStorCoodinator method. :/ found a way to do it with less code anyway. Not sure why apple think you need such a complex string of methods.
Thomas Clayson
+1  A: 

You're getting the error because GFree.momd doesn't exist. From the docs for NSURL's pathForResource:ofType: method:

Return Value The full pathname for the resource file or nil if the file could not be located.

GFree.momd is generated at build time from your .xcdatamodeld file (look in the Build Results for the line starting DataModelVersionCompile and expand it). Have you deleted or renamed that file?

Is it still listed in the Compile Sources section of your build target? (In Xcode expand Targets / [AppName] / Compile Sources).

Just noticed that your debug log says the app is called GFree2 but your code's looking for GFree.momd. Did you rename the project? If the data model file is now called GFree2.xcdatamodeld then you need to change the line that imports the momd file to use the new GFree2 name, too.

Simon Whitaker
hi there. back at work - sorry for late reply. I have a GFree.xcdatamodel file..? But I had to make this manually and I named it myself. I've looked at that line in my build results but it doesn't tell me anything. I'll put the line in my OP.
Thomas Clayson