Where are my core data entities?
Asked Answered
C

3

5

I have a pre-existing project to which I've added Core Data models. I added the Core Data framework, added a data model with entities, and included it in my app's target, along with some generated NSManagedObject classes. It compiles nicely, and now I'd like to add some tests for the entities I've created. Following these instructions, I've set up a logic test base class with a setUp method like so:

- (void)setUp {
    model = [NSManagedObjectModel mergedModelFromBundles:nil];
    NSLog(@"model: %@", model);
    coord = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
    store = [coord addPersistentStoreWithType:NSInMemoryStoreType
                                configuration:nil
                                          URL:nil
                                      options:nil 
                                        error:NULL];
    ctx = [[NSManagedObjectContext alloc] init];
    [ctx setPersistentStoreCoordinator:coord];
}

This compiles and all the objects are created. However, the model has no entities! The NSLog() output looks like so:

2011-10-29 23:56:58.941 otest[42682:3b03] model: (<NSManagedObjectModel: 0x19c6780>) isEditable 1, entities {
}, fetch request templates {
}

So where are my entities? I've poked around the bundle, and there are no .momd files, either. Have I missed some crucial step to get my models to build?

Confection answered 30/10, 2011 at 7:9 Comment(3)
Do you mean you've added entities to your model, or you have added actual instances of entities with data in them?Luff
There's a lot of lazy loading in core data - the docs say loading a model doesn't necessarily load the entities - what happens if you log [model entities]?Luff
@jrturton: I've added entities to my model. [model entities] returns an empty array.Confection
C
7

I did some additional Duck Duck Going and managed to find the information I needed in the this answer. The upshot is that, because a test target doesn't use a "main" bundle, I have to instantiate the test bundle. So instead of this line:

    model = [NSManagedObjectModel mergedModelFromBundles:nil];

I now have these three lines:

    NSBundle *bundle = [NSBundle bundleWithIdentifier:@"com.example.LogicTests"];
    NSURL *url = [bundle URLForResource:@"MyModels" withExtension:@"momd"];
    model = [[NSManagedObjectModel alloc] initWithContentsOfURL:url];

The bundle identifier comes directly from my target build info, while "MyModels" comes from my data model file, which is named "MyModels.xcdatamodeld" and included in the app bundle as "MyModels.momd". And that, of course, contains my models.

Confection answered 4/11, 2011 at 4:29 Comment(1)
Great, this answer helped me, thanx. But I was using Apple's code to work with Core Data, so I've just changed [NSBundle mainBundle]; to [NSBundle bundleWithIdentifier:@"com.example.someProject"];Verner
G
0

Look here. I'm using code that is generated when you are creating project with CoreData. I hope that would help you to solve your problems:

pragma mark Core Data stack

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


/**
 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 by merging all of the models found in the application bundle.
 */
- (NSManagedObjectModel *)managedObjectModel 
{   
    if (managedObjectModel != nil) 
    {
        return managedObjectModel;
    }
    managedObjectModel = [[NSManagedObjectModel mergedModelFromBundles:nil] retain];    
    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: @"CoreDB.sqlite"]];
    
    NSError *error = nil;
    persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                             [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, 
                             [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
    if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options 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.
         */
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }
    return persistentStoreCoordinator;
}
Gooseherd answered 30/10, 2011 at 7:42 Comment(1)
I tried that, too, but wasn't able to figure out what might be missing, but I'll pour over it again.Confection
B
0

If your database is within / from a framework, you need to load it using its corresponding Bundle.

I found a solution in Swift with MagicalRecord:

let frameworkBundle = Bundle(for: AClassFromTheFramework.self)
let managedObjectModel = NSManagedObjectModel.mergedModel(from: [frameworkBundle])
MagicalRecord.setShouldAutoCreateManagedObjectModel(false)
NSManagedObjectModel.mr_setDefaultManagedObjectModel(managedObjectModel)
MagicalRecord.setupCoreDataStack(withAutoMigratingSqliteStoreNamed: "db.sqlite")

Loading the managaed object model from the bundle and setShouldAutoCreateManagedObjectModel set to false did the trick!

Ballenger answered 3/1, 2018 at 21:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.