I'm trying to update a UITableView in a view called "HomeViewController" to show the new objects that I've added. But the NSFetchedResultsController doesn't update after I've finished creating a new one. I have the following code in various documents:
HomeViewController.h
- (void)saveNewShindyToDatabaseForName:(NSString *)name
details:(NSString *)details
dateAndTime:(NSDate *)dateAndTime
location:(CLLocation *)location
timePosted:(NSDate *)postedTime
{
if (!self.shindysDatabase) {
NSURL *url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
self.shindysDatabase = [[UIManagedDocument alloc] initWithFileURL:url];
}
dispatch_queue_t saveQ = dispatch_queue_create("Shindy Creator", nil);
dispatch_async(saveQ, ^{
[self.shindysDatabase.managedObjectContext performBlock:^{
[Shindy setupShindyForSaveToDatabaseForName:name
details:details
dateAndTime:dateAndTime
location:location
timePosted:postedTime
inManagedObjectcontext:self.shindysDatabase.managedObjectContext];
}];
});
NSError *error = nil;
if (![self.shindysDatabase.managedObjectContext save:&error]) {
NSLog(@"%@", error.userInfo);
}
}
- (void)setupFetchedResultsController
{
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Shindy"];
NSSortDescriptor *nameSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES];
NSSortDescriptor *photoSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"photo" ascending:YES];
NSSortDescriptor *detailSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"details" ascending:YES];
NSSortDescriptor *dateAndTimeSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"dateAndTime" ascending:YES];
NSSortDescriptor *timePostedSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"timePosted" ascending:YES];
request.sortDescriptors = [NSArray arrayWithObjects:nameSortDescriptor, photoSortDescriptor, detailSortDescriptor, dateAndTimeSortDescriptor, timePostedSortDescriptor, nil];
self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request
managedObjectContext:self.shindysDatabase.managedObjectContext
sectionNameKeyPath:nil
cacheName:nil];
}
Shindy+SQL.m (An NSManagedObject subclass of the entity, "Shindy")
+ (Shindy *)setupShindyForSaveToDatabaseForName:(NSString *)name
details:(NSString *)details
dateAndTime:(NSDate *)dateAndTime
location:(CLLocation *)location
timePosted:(NSDate *)postedTime
inManagedObjectcontext:(NSManagedObjectContext *)context
{
Shindy *shindy = [NSEntityDescription insertNewObjectForEntityForName:@"Shindy" inManagedObjectContext:context];
__block NSString *nameString = name;
__block FBProfilePictureView *profileImage = nil;
if (FBSession.activeSession.isOpen) {
[[FBRequest requestForMe] startWithCompletionHandler:
^(FBRequestConnection *connection, NSDictionary<FBGraphUser> *user, NSError *error) {
if (!error) {
nameString = user.name;
profileImage.profileID = user.id;
}
}];
}
NSData *imageData = nil;
for (NSObject *obj in [profileImage subviews]) {
if ([obj isMemberOfClass:[UIImageView class]]) {
UIImageView *objImg = (UIImageView *)obj;
imageData = UIImagePNGRepresentation(objImg.image);;
break;
}
}
shindy.name = name;
shindy.dateAndTime = dateAndTime;
shindy.timePosted = postedTime;
shindy.details = details;
shindy.photo = imageData;
return shindy;
}
The method, - (void)setupFetchedResultsController: is called when the view is initially loaded (but not in the viewDidLoad or viewWillAppear method). And my - (void)saveNewShindyToDatabaseForName: function is called in a separate view controller once the user is finished entering their data. In other words, it's public API, but the NSManagedObjectContext remains within the HomeViewController for delegation. Also, the delegates & data sources for my code are set properly.
I have tried to force every kind of fetch; whether it be through the managedObjectContext, or the fetchedResultsController. I have also set an NSLog in various places of my code to ensure that the data is getting through to the HomeViewController. I have also set another NSLog to ensure that both the fetchedResultsController & managedObjectContext is not nil.
Everything seems to check out, and I don't get any sort of errors from the other default errors currently within my code.
I fear that this has to do something with the NSSortDescriptors I have in my - (void)setupFetchedResultsController: method, but I have also tried to configure those in various ways to no avail. There is a definite connection to my managedObjectContext & my fetchedResultsController as well, so that's not the problem.
I've simply run out of things to try. Perhaps, someone on here has some insight.
For jrturton...
I have implemented the following code in my - (void)saveNewShindyToDatabaseForName: method after all of the code that was there originally. It looks like this:
- (void)saveNewShindyToDatabaseForName:(NSString *)name
details:(NSString *)details
dateAndTime:(NSDate *)dateAndTime
location:(CLLocation *)location
timePosted:(NSDate *)postedTime
{
// All of the code originally in this method is here...
if ([self.fetchedResultsController managedObjectContext] == self.shindysDatabase.managedObjectContext) {
NSLog(@"MOC's are the same.");
}
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Shindy"];
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"details" ascending:YES];
request.sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSError *error = nil;
NSArray *detailsArray = [self.shindysDatabase.managedObjectContext executeFetchRequest:request error:&error];
if (error) {
NSLog(@"error: %@", error.userInfo);
}
NSLog(@"details: %@", detailsArray);
}
What all of this returns is that to answer your second possible answer, the MOC's are definitely the same. However, it appears as though the new objects are not actually getting saved into Core Data. Or I'm not pulling them back out properly.
The only way I could think of logging what is inside of my Core Data without getting an unrecognized selector error was by creating a new request for the correct entity, and then executing a fetch, then logging the results of that fetch, which, in this case, returned nothing.
I'm going to assume then that my problem lies within my code not saving the new objects to Core Data. With that said, can you identify anywhere I'm not properly saving these objects to my context so that it can be put into my Core Data model for retrieval later? Or do I need to setup a different method other than requesting to log what's being saved into my Core Data?