Reputation: 47348
I've ran into a puzzling issue:
I have only one method defined for inserting objects into Core Data. I'm trying to insert data in 2 different ways: one is from a UITableView with the + button. The other is from a regular UIViewController by calling the method below.
At the end of the method, the method returns a NSManagedObject in both cases, but the fetchedObjects count is incremented only in the case of inserting from a UITableViewController.
If I load the UITableViewController first, all subsequent calls to the method correctly increment the number of fetched objects. If I do not do so, the number stays the same, even though NSManagedObjects are returned from the method. On subsequent app restart, the "invisible" objects are loaded again and become visible
It seems to me that the issue is with the ManagedObjectContext, but I do not see where I incorrectly set it.
The project uses iOS5, ARC and storyboards.
-(Event*)insertAndReturnNewEventWithSeverity:(int)type
{
// Create a new instance of the entity managed by the fetched results controller.
NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];
NSEntityDescription *entity = [[self.fetchedResultsController fetchRequest] entity];
Event *newManagedObject = (Event*)[NSEntityDescription insertNewObjectForEntityForName:[entity name] inManagedObjectContext:context];
newManagedObject.insert_datetime = [NSDate date];
NSError *error = nil;
if (![context save:&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.
*/
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
// abort();
}
NSLog(@"objects: %i", self.fetchedResultsController.fetchedObjects.count );
return newManagedObject;
}
There's only one managedObject context, which is initialized within the app delegate.
-(NSManagedObjectContext*)managedObjectContext
{
if(__managedObjectContext!=nil)
{
return __managedObjectContext;
}else{
self.managedObjectContext = self.appDelegate.managedObjectContext;
}
return __managedObjectContext;
}
UPDATE:
Adding my UIViewController
as a delegate to the NSFetchedResultsController
, and adding didChangeObject and didChangeSection causes the .fetchedObjects property to correctly increment itself!
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.coreDataManager.fetchedResultsController.delegate = self;
}
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath
{
NSLog(@"Changed object");
}
- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo
atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type
{
NSLog(@"Changed section");
}
Thank you for your help!
Upvotes: 2
Views: 3376
Reputation: 6844
In order to get the NSFetchedResultsController's fetchedObjects to count properly, you need to set a delegate to your NSFetchedResultsController.
What Apple says about that:
The Controller’s Delegate
If you set a delegate for a fetched results controller, the controller registers to receive change notifications from its managed object context. Any change in the context that affects the result set or section information is processed and the results are updated accordingly. The controller notifies the delegate when result objects change location or when sections are modified (see NSFetchedResultsControllerDelegate). You typically use these methods to update the display of the table view.
Upvotes: 1
Reputation: 2150
NSFetchedResultsController requires that a delegate be set to monitor changes in fetch results.
A controller thus effectively has three modes of operation, determined by whether it has a delegate and whether the cache file name is set.
No tracking: the delegate is set to nil. The controller simply provides access to the data as it was when the fetch was executed.
> Memory-only tracking: the delegate is non-nil and the file cache name is set to nil. The controller monitors objects in its result set and updates section and ordering information in response to relevant changes.
Full persistent tracking: the delegate and the file cache name are non-nil. The controller monitors objects in its result set and updates section and ordering information in response to relevant changes. The controller maintains a persistent cache of the results of its computation.
Upvotes: 3