3

First off, I'll make mention that I've seen lots of answers to this type of question on this site and others, but I can't seem to relate those solutions to my problem. I do apologize, however, if the answer I'm looking for already exists or turns out to be incredibly simple (although I'm definitely hoping that's the case).

I'm attempting to add Core Data functionality to my existing application and I've taken the following steps:

a. Added the Core Data framework and CoreData imports to the relevant files
b. Added a Data Model file to my Resources folder named "MyProject.xcdatamodeld" and added entities/attributes to the data model. I've also generated a class for each entity.
c. Added the following properties/method to my AppDelegate.h:

@property (readonly, strong, nonatomic) NSManagedObjectModel* managedObjectModel;
@property (readonly, strong, nonatomic) NSManagedObjectContext* managedObjectContext;
@property (readonly, strong, nonatomic) NSPersistentStoreCoordinator* persistentStoreCoordinator;

-(NSString*)applicationDocumentsDirectory;

d. Added the following code to my AppDelegate.m:


@synthesize managedObjectModel = __managedObjectModel;
@synthesize managedObjectContext = __managedObjectContext;
@synthesize persistentStoreCoordinator = __persistentStoreCoordinator;

-(NSManagedObjectContext *)managedObjectContext
{
    if (__managedObjectContext != nil)
    {
        return __managedObjectContext;
    }

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];

    if (coordinator != nil)
    {
        __managedObjectContext = [[NSManagedObjectContext alloc] init];
        [__managedObjectContext setPersistentStoreCoordinator:coordinator];
    }

    return __managedObjectContext;
}

-(NSManagedObjectModel *)managedObjectModel
{
    if (__managedObjectModel != nil)
    {
        return __managedObjectModel;
    }

    __managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil];

    return __managedObjectModel;
}

-(NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
    if (__persistentStoreCoordinator != nil)
    {
        return __persistentStoreCoordinator;
    }

    NSURL *storeUrl = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent: @"MyProject.sqlite"]];
    NSError *error = nil;

    __persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];

    if(![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:nil error:&error])
    {
        /*Error for store creation should be handled in here*/
    }

    return __persistentStoreCoordinator;
}

-(NSString *)applicationDocumentsDirectory
{
    return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
}

The problem is, when this line executes:

__managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil];

I'm getting an NSInvalidArgumentException saying a nil object is being inserted into an NSArray.

I've tried replacing that code with the following:

NSURL* modelURL = [[NSBundle mainBundle] URLForResource:@"MyProject" withExtension:@"momd"];
__managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];

and with that I'm not getting any exceptions, but after executing those lines __managedObjectModel is still null.

I can't seem to figure out what's wrong. Any ideas?

(As a side note, I'm using ARC which is why you don't see any calls to retain).

Any help/suggestions are much appreciated.

Thanks,

B.J.

Benny
  • 1,508
  • 3
  • 18
  • 34
  • 1
    By chance, have you renamed your model file after you added it? I once had a problem when I renamed my model. To fix, I had to copy the model out of the project directory, remove it from the project, and then re-add it. I'll try to find the SO post that listed that issue. – mservidio Jan 20 '12 at 22:04
  • I can't find the post that fixed my issue, though see here: http://stackoverflow.com/questions/7044643/core-data-model-files-does-not-load-on-rename. Perhaps it's not included in your build target? – mservidio Jan 20 '12 at 22:07
  • Yes, that was the problem. Removing and re-adding the model file seems to have fixed everything. Thanks a lot for the help. (If you add that comment as an answer, I'll mark it as correct.) – Benny Jan 23 '12 at 15:24
  • thx. I've added my comment as an answer. – mservidio Jan 23 '12 at 15:50

2 Answers2

4

This issue can arise if you have renamed your model file after you added it. I once had a problem when I renamed my model. To fix, I had to copy the model out of the project directory, remove it from the project, and then re-add it.

mservidio
  • 12,817
  • 9
  • 58
  • 84
1

Are you actually merging multiple model files - or just adding a fresh Core Data backing store?

Your code looks like a template to merge...

My Core Data stack looks like this:

    #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];
        [__managedObjectContext setUndoManager:nil];
    }
    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;
    }
    NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"FlurryStats" withExtension:@"momd"];
    __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 = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"FlurryStats.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;
}
bandejapaisa
  • 26,576
  • 13
  • 94
  • 112