FetchedResultsController and displaying data from 3 nested entities in one UITableViewCell - ios

Could somebody explain me how can I display in one tableViewCell data from three entities connected by relationship?
I have 3 entities, let it be User, Device, and Alert. Relationships : User has many Devices and these devices have many Alerts.
In my AlertsTableViewController I want to display every alerts with user_name property which is included in User entity.
Should I start my fetch request by setting entity for name User or Alert?.
- (NSFetchedResultsController *)fetchedResultsController
{
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"????????" inManagedObjectContext:_managedObjectContext];
[fetchRequest setEntity:entity];
// Set the batch size to a suitable number.
[fetchRequest setFetchBatchSize:12];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"created_at" ascending:NO];
NSArray *sortDescriptors = #[sortDescriptor];
[fetchRequest setSortDescriptors:sortDescriptors];
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:_managedObjectContext sectionNameKeyPath:nil cacheName:#"Alerts"];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
NSError *error = nil;
if (![self.fetchedResultsController performFetch:&error])
{
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
}
return _fetchedResultsController;
}
My TableView methods:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"AlertsTableViewCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
User *u = [[self fetchedResultsController] objectAtIndexPath:indexPath];
//I know how to display User with details of devices by looping nsset but how to display every alerts with User.name?
for (Device *device in u.devices) {
[cell.textLabel setText:device.someProperty];
}
return cell;
}

When you like to display Alerts, in most simple cases (like yours) you will set the fetch request entity to #"Alert".
To select only Alerts that belong to a given user you will need to define a predicate for your fetch request:
fetchRequest.predicate = [NSPredicate predicateWithFormat:#"device.user = %#",<User object or User objectID>];
The User object or objectID will be known to you from the app user selection, or, if you have another unique identifier for each user (like the userName property) you could include that in your predicate:
fetchRequest.predicate = [NSPredicate predicateWithFormat:#"device.user.name = %#",userNameVariable];
In most cases, the LAST thing you want to do is loop over a set of NSManagedObjects as they will fire faults one by one and give you a really bad user experience (especially in cellForRow...).
Get the data you like to display before you need to supply it to the view.
Edit:
In that spirit, if you like to display the someProperty value in your AlertsTableViewController you should also add:
fetchRequest.relationshipKeyPathsForPrefetching = #[#"device"];
So that the Device will be fetched along with Alert object.
Obviously, you have to change your cellForRow... method to accept Alert objects from the FRC.

Related

Core Data to-many relationship fetching

I have the following set up in core data: A Dish entity, with many ingredients, and a Ingredient entity with one dish.
I'm having trouble fetching my to-many relationship data, i.e. the ingredients for a certain dish. I'm trying to populate my collection view cells with the ingredients associated to each dish.
I have my core data model set up as follows:
I have tried various methods to fetch the data.
One of the things I've tried is to do the following: Dish *dish = [self.fetchedResultsController objectAtIndexPath:indexPath]; and then NSLog dish.ingredients (which returns a NSSet), but the returns the whole core data item, i.e., the createdAt date, the name and everything, together with the unformatted version of the ingredients for that dish.
Another thing i tried was to create a new instance of the Ingredient entity with Ingredient *ingredient = [dish.ingredients valueForKeyPath:#"ingredientName"];, but that returns an unformatted string (I want it UTF8 encoded before it's displayed because it contains special characters).
A lot of solutions when googling suggests using NSPredicate, but I just can't figure out how to use that. I'm still new to core data, and XCODE in general, so any help here would be appreciated, i.e. where do you implement the NSPredicate, and what would the correct predicate be in my case?
A bit of supporting code:
my collectionViewController:
- (NSFetchedResultsController *)fetchedResultsController
{
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
// Edit the entity name as appropriate.
NSManagedObjectContext* context = [RKObjectManager sharedManager].managedObjectStore.mainQueueManagedObjectContext;
self.managedObjectContext = context;
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Dish" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
// Set the batch size to a suitable number.
[fetchRequest setFetchBatchSize:20];
// Edit the sort key as appropriate.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"createdAt" ascending:NO];
NSArray *sortDescriptors = #[sortDescriptor];
[fetchRequest setSortDescriptors:sortDescriptors];
// Edit the section name key path and cache name if appropriate.
// nil for section name key path means "no sections".
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:#"Master"];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
NSError *error = nil;
if (![self.fetchedResultsController performFetch:&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();
}
return _fetchedResultsController;
}
cellForItemAtIndexPath:
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
FOFPhotoCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"photo" forIndexPath:indexPath];
self.object = [self.fetchedResultsController objectAtIndexPath:indexPath];
Dish *dish = [self.fetchedResultsController objectAtIndexPath:indexPath];
Ingredient *ingredient = ???;
cell.backgroundColor = [UIColor lightGrayColor];
[cell.imageView setImageWithURL:[NSURL URLWithString:[[NSString stringWithFormat:#"http://192.168.0.3:4000%#", dish.dishImage] description]] completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType) {
}];
cell.titleLabel.text = dish.dishName;
cell.headerLabel.text = dish.dishHeader;
cell.ingredientsLabel.text = [NSString stringWithFormat:#"%#", nil];
NSLog(#"%#", ingredient);
[self.collectionView reloadItemsAtIndexPaths:[NSArray arrayWithObject:indexPath]];
return cell;
}
The simple way is your first approach and then only use the attributes that you care about from the ingredients. Core Data is more about programming with objects than it is about the underlying database, so attempting to simulate DB queries isn't usually the right approach.
I also recommend getting rid of all the valueForKey stuff and using actual object properties so that the code is a bit clearer and the compiler can help you out more with data types.
If you're looking for Ingredients only for a one specific Dish, you have to set your fetchRequest for Ingredients (and not Dish) and set the predicate on Dish. To make the following code work, you may need first to Create NSManagedObject Subclasses (with the help of Xcode Editor button).
#import "Dish.h"
#import "Ingredient.h"
- (NSFetchedResultsController *)fetchedResultsController
{
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:#"Ingredient"];
[fetchRequest setFetchBatchSize:20];
//if dishname are unique values, set your predicate on it.
//You can also set your predicate on the dishID if dishName are not unique values (several dishes with a same name)
NSString *theDishIWant = #"Ratatouille"; //whatever Dish name you want
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"dish.dishName == %#", theDishIWant];
[fetchRequest setPredicate:predicate];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"ingredientname" ascending:YES];
[fetchRequest setSortDescriptors:#[sortDescriptor];
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:[RKObjectManager sharedManager].managedObjectStore.mainQueueManagedObjectContext sectionNameKeyPath:nil cacheName:nil];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
NSError *error = nil;
if (![self.fetchedResultsController performFetch:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
NSLog (#"%#", _fetchedResultsController);
return _fetchedResultsController;
}
Your configureCell: atIndexPath: method may look like this:
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
Ingredient *ingredient = [self.fetchedResultsController objectAtIndexPath:indexPath];
cell.textLabel.text = ingredient.ingredientName;
cell.detailTextLabel.text = ingredient.ingredientValue;
}

IOS Core Data Cardinality issue

I'm writing a simple application using TableViews and Core Data that shows a list of students in the first level and when clicked on a cell, it shows the names of the courses that student takes. I set student->courses as toMany, courses->student as toOne. This is how i pass the Student entity to course view controller for using its managedObjectContext:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
Student *info = [_fetchedResultsController objectAtIndexPath:indexPath];
CoursesTableViewController *courseViewController = [[CoursesTableViewController alloc] initWithStudentInfo:info];
[self.navigationController pushViewController:courseViewController animated:YES];
}
This is how i create courses inside the courses view controller(I want only three courses as named below, numberofrow is supposed to assure that):
- (void)viewDidLoad
{
[super viewDidLoad];
id <NSFetchedResultsSectionInfo> sectionInfo = [self.fetchedResultsController sections][0];
int numberofrow = [sectionInfo numberOfObjects];
NSLog(#"%d",numberofrow);
NSLog(#"%d",[self.fetchedResultsController sections].count);
if(numberofrow <=2){
NSLog(#"creating courses");
[self insertNewObject:#"comp319"];
[self insertNewObject:#"comp314"];
[self insertNewObject:#"comp316"];
}
}
- (void)insertNewObject:(NSString *) str{
NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];
NSEntityDescription *entity = [[self.fetchedResultsController fetchRequest] entity];
NSManagedObject *newManagedObject = [NSEntityDescription insertNewObjectForEntityForName:[entity name] inManagedObjectContext:context];
[newManagedObject setValue:str forKey:#"course_name"];
NSError *error = nil;
if (![context save:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
}
How i create the fetchedResultsController inside courses View Controller:
- (NSFetchedResultsController *)fetchedResultsController
{
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
// Edit the entity name as appropriate.
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Courses" inManagedObjectContext:self.studentInfo.managedObjectContext];
[fetchRequest setEntity:entity];
// Set the batch size to a suitable number.
[fetchRequest setFetchBatchSize:20];
// Edit the sort key as appropriate.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"course_name" ascending:NO];
NSArray *sortDescriptors = #[sortDescriptor];
[fetchRequest setSortDescriptors:sortDescriptors];
// Edit the section name key path and cache name if appropriate.
// nil for section name key path means "no sections".
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.studentInfo.managedObjectContext sectionNameKeyPath:nil cacheName:nil];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
NSError *error = nil;
if (![self.fetchedResultsController performFetch:&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();
}
return _fetchedResultsController;
}
Finally the problem is that when I create the first student and click on it, NSLog in viewDidLoad of courses view controller above prints "creating courses", however when i create the second student it does not and also numberofrow prints 3 where it should have printed 0 since it is a new student instance.
Thanks for any help.
Replace
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Courses" inManagedObjectContext:self.studentInfo.managedObjectContext];
[fetchRequest setEntity:entity];
With
// my comment : entity here has to be your student name, why 'course'
// and also replace your search key from 'yourCourseNameKey' with 'yourStudentNameKey'
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Your Student Name" inManagedObjectContext:self.studentInfo.managedObjectContext];
[fetchRequest setEntity:entity];
You need to get number of Students but you query number of Courses
You do not set a predicate on the fetch provided to the fetched request controller so you aren't searching for courses for the selected student and creating then if they aren't there. Not that that is ideal anyway (and wouldn't work because you aren't setting a relationship between the student and all of the courses).
So, most likely you should have a set of courses and a set of students. The relationship should be many:many as a course really has multiple students and each student takes multiple courses (or could anyway).
Now, your students and courses would be created 'up-front' and then your view controllers simply deal with fetching, displaying and connecting (establishing the relationships) the objects.

ios core data to AZ indexed tableview

I'm trying to show the values of my core data model to an A-Z indexed table based on the first letter on my attributes (similar to the iOS address book app). The "Favorites" entity of my core data model has 2 attributes: username and status. I want to display only the usernames with status = accepted to the A-Z indexed table.
Here is my code:
- (NSFetchedResultsController *)fetchedResultsController {
if (fetchedResultsController != nil) {
return fetchedResultsController;
}
NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Favorites" inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];
NSString *status = #"accepted";
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"status == %#",status];
[fetchRequest setPredicate:predicate];
// Create the sort descriptors array.
NSSortDescriptor *usernameDescriptor = [[NSSortDescriptor alloc] initWithKey:#"username" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:usernameDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
// Create and initialize the fetch results controller.
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:#"username" cacheName:#"Root"];
self.fetchedResultsController = aFetchedResultsController;
fetchedResultsController.delegate = self;
return fetchedResultsController;
}
Now when I'm trying to access the section name I get (null)
-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
NSLog(#"%#",[[[fetchedResultsController sections] objectAtIndex:section] name]);
return [[[fetchedResultsController sections] objectAtIndex:section] name];
}
Also I thing that with that way I will get the the name and not the first char in order to display it as a section title.
You need to access the sectionsInfo object properly:
id <NSFetchedResultsSectionInfo> info =
[fetchedResultsController sections][section];
return [info name];
However, this will give you a heading for each unique name, probably not want you want. Instead, you have to give your entity a transient property e.g. NSString *sectionIdentifier and write a getter for it that returns the first letter of the username attribute.
If want an index from A-Z running down on the right edge of the table view you additionally have to implement:
sectionIndexTitlesForTableView: and
tableView:sectionForSectionIndexTitle:atIndex:.
If you still get null for your titles, maybe they are not set or persisted in your entity? Maybe you got zero results? Maybe your fetchedResultsController is nil? There are a number of flaws in your data model, so this seems quite possible.
Your entity name Favorites is plural. That is not logical, you should name it Favorite as one instance only describes one favourite.
The status is a string which is also very inefficient. Instead, you should use a number and apply some enum scheme.
The username is a property of Favorite. That seems also very messy because presumably, you also have a User entity which has a username attribute. You should use a relationship to model this.
use NSFetchedResultsController's sectionIndexTitles function to get array of first char

Updating an NSFetchedResultsController with an NSPredicate that uses the current time

I have an application that needs to filter objects based on timestamps. For example, lets say I want to filter an Event to only display Events that are in the past. I want to then display them in a UITableView. I would set up an NSFetchedResultsController like so:
- (NSFetchedResultsController *)fetchedResultsController
{
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
// Edit the entity name as appropriate.
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Event" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
// Set the batch size to a suitable number.
[fetchRequest setFetchBatchSize:20];
// Edit the sort key as appropriate.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"timeStamp" ascending:NO];
NSArray *sortDescriptors = #[sortDescriptor];
// Filter based on only time stamps in the past
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"timeStamp < %#", [NSDate date]];
fetchRequest.predicate = predicate;
[fetchRequest setSortDescriptors:sortDescriptors];
// Edit the section name key path and cache name if appropriate.
// nil for section name key path means "no sections".
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:nil];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
NSError *error = nil;
if (![self.fetchedResultsController performFetch:&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();
}
return _fetchedResultsController;
}
My question is this: what is the best way to update this view so that the filter is based on the current time? My existing solution is to set up a method like this:
- (void)updateFetchedResultsController {
self.fetchedResultsController = nil;
[self.tableView reloadData];
}
Then I call that method on viewWillAppear: or viewDidAppear:. This works unless the user stays on the screen for a while.
I could also use an NSTimer and call updateFetchedResultsController once a minute or so but that causes issues if the user is scrolling through the table. Is there a better way to check if the data has changed? Since the data isn't changing I can't rely on any save events.
You only ever need to change the data on display when an items time is no longer valid. It has a date so you can calculate how long into the future that is and set a timer. You order the data so the next item to expire is always the first in the list.
To finesse, you can check for scrolling when the timer expires and delay the reload until the scroll animations have completed.

Core Data: How to pass a managed object to a UITableViewCell and do a fetchRequest from there?

I have a UITableView With a custom Cell that contains another UItableView. I need to pass an object to it, and then execute a fetchrequest based on this object.
From my cellForRowAtIndexPath method, I am passing a Managed Object to the custom Cell, like this:
TWHistoryViewStandardExpendedCell *cell = (TWHistoryViewStandardExpendedCell *)[tableView dequeueReusableCellWithIdentifier:ExpandedCell];
if (cell == nil) {
cell = (TWHistoryViewStandardExpendedCell *)[[[NSBundle mainBundle] loadNibNamed:#"HistoryViewStandardCellExpanded" owner:self options:nil] objectAtIndex:0];
}
Day *aDay = (Day *)[_fetchedResultsController objectAtIndexPath:indexPath];
[cell setViewingDay: aDay]; // NSLog here returns the expected object! :)
return cell;
This way, I should be able to execute a fetchRequest based on this object, from my custom Cell.
On my custom UItableViewCell, I do this:
- (void) awakeFromNib
{
[self fetchRequest];
}
- (void)fetchRequest {
NSError *error;
if (![[self fetchedResultsController] performFetch:&error]) {
// Update to handle the error appropriately.
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
exit(-1); // Fail
}
}
Some details about my fetchedResultsController: see in comments that my managed object returns null here!
- (NSFetchedResultsController *)fetchedResultsController
{
if (_fetchedResultsController) {
return _fetchedResultsController;
}
NSManagedObjectContext * managedObjectContext =
[myAppDelegate managedObjectContext];
NSEntityDescription *entity =
[NSEntityDescription entityForName:#"Clock"
inManagedObjectContext:managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:entity];
[fetchRequest setPredicate: [NSPredicate predicateWithFormat:#"day == %#", _viewingDay]];
NSLog(#"_viewingDay: %#", _viewingDay); // returns null! :(
NSLog(#"_viewingDay.clocks: %#", _viewingDay.clocks); // also returns null!
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"clockIn" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
//
[fetchRequest setSortDescriptors:sortDescriptors];
[fetchRequest setFetchBatchSize:20];
NSFetchedResultsController *theFetchedResultsController =
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:managedObjectContext
sectionNameKeyPath:nil
cacheName:nil];
_fetchedResultsController = theFetchedResultsController;
_fetchedResultsController.delegate = self;
return _fetchedResultsController;
}
Based on this, I have overriden my setViewingDay method:
- (void)setViewingDay:(Day *)viewingDay
{
if (_viewingDay != viewingDay) {
_viewingDay = viewingDay;
NSLog(#"setViewingDay: %#", _viewingDay); // returns expected object! =)
[self fetchRequest];
}
}
Still, after this, my UITableView remains empty. My numberOfRowsInSection method keeps returning 0!
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
id <NSFetchedResultsSectionInfo> sectionInfo = [[_fetchedResultsController sections] objectAtIndex:section];
NSLog(#"numberOfRowsInSection %d", [sectionInfo numberOfObjects]);
return [sectionInfo numberOfObjects];
}
I also added a UIButton that performs the fetch request. Hoping to find a situation where the fetchRequest was being performed before the actual setting of my reference to the managed object. So I click on it, do perform a fetch. And nothing! No rows whatsoever.
EDIT:
However, the NSLogs bellow, from inside my fetchResultsController do return an object then, by using a supporting UIBUtton and IBAction. But still no rows!
NSLog(#"_viewingDay: %#", _viewingDay);
NSLog(#"_viewingDay.clocks: %#", _viewingDay.clocks);
Supporting UIButton to perform a fetch:
- (IBAction)fetchem:(UIButton *)sender {
[_clocksTableView reloadData];
_fetchedResultsController = nil;
[NSFetchedResultsController deleteCacheWithName:nil];
[self fetchRequest];
NSLog(#"\n\nfetchem: %# \n\nvd: %# \n\nclocks: %# ", _fetchedResultsController.description, _viewingDay.description, _viewingDay.clocks.description );
}
Anything I might be missing here?
Thank you!
EDIT 2:
I just realized that setting my predicate to (1 == 1), returns all clocks. Confirming that my resultsController is correctly set up. There may be something wrong with my predicate... I don't see what. I have a similar predicate in a previous controller and works great.
Predicate is very simple, nothing fancy:
[fetchRequest setPredicate: [NSPredicate predicateWithFormat:#"day == %#", _viewingDay]];
I have a Clock and Day entities.
A Day has many clocks. 1 to many relationship.
A clock has one day, and one day only.
The fetchRequest above should have been returning all clocks from that day. But it's not?
1) awakeFromNib gets execute the moment you instantiate the cell and therefore before you set the viewing day. It also doesn't get execute if the cell is reused, so you should trigger the fetch request separately.
2) How does the fetchedResultsController property inside the cell get set?
EDIT 1:
From the datamodel and the predicate, it would seem the relationship between clock and day doesn't get set correctly.
EDIT 2:
Quoting the asker's comment from below: "The problem was fixed after inserting: [self fetchRequest] inside my overriden setter."

Resources