0

I am trying to load a table view with cells that represents people, loaded from core data. This is how I get the context:

@property (nonatomic,strong) NSManagedObjectContext* managedObjectContext;

...

- (NSManagedObjectContext*) managedObjectContext {
    if(!_managedObjectContext) {
        NSFileManager* manager= [NSFileManager defaultManager];
        NSURL* URL= [manager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask].firstObject;
        URL= [URL URLByAppendingPathComponent:@"PeopleDocument"];
        UIManagedDocument* document= [[UIManagedDocument alloc]initWithFileURL:URL];

        if([manager fileExistsAtPath:URL.path]) {
            [document openWithCompletionHandler:^(BOOL success) {
            }];
        } else {
            [document saveToURL:URL forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success) {
            }];
        }
        NSManagedObjectContext* context= [document managedObjectContext];
        _managedObjectContext= context;
    }
    return _managedObjectContext;
}

Then just the first time that I run the app I insert a new entity and save the context:

[NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext: self.managedObjectContext];
[self.managedObjectContext save:NULL];

I also tried to log the result of save:, it returns YES and there's no error. But the context isn't truly saved: the second time that I run the app the fetched entities array is empty.

Update

Something even stranger happened: reading this answer to another similar question, I've found a method to force the document to be saved:

- (void) save {
    NSError *error = nil;

    if (![self.managedObjectContext save:&error]) {
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }

    [self.managedDocument saveToURL:self.managedDocument.fileURL forSaveOperation:UIDocumentSaveForOverwriting completionHandler:^(BOOL success)
    {
        NSLog(@"Saved: %d",success);
    }];

}

So I execute this code the first time that I run the app:

#if FIRST_TIME
    [NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext: self.managedObjectContext];
    [self save];
#endif

After it, if I set FIRST_TIME to zero, the second time that I run the app I get empty records. But if the 3rd time that I run the app I set again FIRST_TIME to 1, then I get all the records that I created before (plus the one that gets created). This means that if I create and save new entities, all the entities that I created before are fetched correctly, otherwise no entity is fetched.

PS: I double checked: the managed object context is the exact one returned by self.managedDocument.managedObjectContext.

Community
  • 1
  • 1
Ramy Al Zuhouri
  • 21,580
  • 26
  • 105
  • 187

2 Answers2

0

It sounds like you are not getting the same self.managedObjectContext in your code. Did you double check that the managedObjectContext that you access in your method is the same as the first one that you created in the first method you pasted? I would step through those two methods and make sure they are the same object.

It looks like in the first method you are not setting self.managedObjectContext but just setting _managedObjectContext. If those two are the same thing, you should have something like this somewhere in your file:

@synthesize managedObjectContext = _managedObjectContext;
Enrico Susatyo
  • 19,372
  • 18
  • 95
  • 156
  • I made some debug: the managed object context returned by the getter is always the same. The property was already synthesized. I'll add the property declaration on the question. – Ramy Al Zuhouri Apr 06 '14 at 10:16
0

I just changed my way to create the managed object context. Instead of using a UIManagedDocument, I created the context with alloc+initWithConcurrencyType:, then I set it's persistent store coordinator:

- (NSManagedObjectContext*) managedObjectContext {
    if(!_managedObjectContext) {
        NSURL* URL= [[NSBundle mainBundle] URLForResource:@"People" withExtension:@"momd"];
        NSManagedObjectModel* model= [[NSManagedObjectModel alloc]initWithContentsOfURL:URL];
        NSPersistentStoreCoordinator* storeCoordinator= [[NSPersistentStoreCoordinator alloc]initWithManagedObjectModel: model];
        NSURL* storeURL= [[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask].lastObject;
        storeURL= [storeURL URLByAppendingPathComponent:@"MOC.sqlite"];

        NSError* error;
        [storeCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error];
        if(error) {
            NSLog(@"Cannot create new store %@",error);
            return nil;
        }

        _managedObjectContext= [[NSManagedObjectContext alloc]initWithConcurrencyType: NSMainQueueConcurrencyType];
        _managedObjectContext.persistentStoreCoordinator= storeCoordinator;
    }

    return _managedObjectContext;
}

I believe that also the other way is correct, but maybe I had to save the document in another way.

Ramy Al Zuhouri
  • 21,580
  • 26
  • 105
  • 187