Reputation: 861
I'm trying to implement a UIViewController that has 2 UITableViews (on iPad): one to display sections of a checklist, and another to display the questions within the selected/section.
I've setup the NSFetchedResultsController and I am able to successfully fetch objects from the persistent store, however none of the NSFetchedResultsController or UITableView delegate methods are being called.
I do set the class to implement the respective protocols, and do set the FRC and TableView delegates to "self".
I've put breakpoints in each of the delegate methods but never reach any of them (yes, I'm running with breakpoints enabled and can step through other parts of the code just fine).
I appreciate any insight offered as to why delegate methods would not be called in these cases: 1) when [FRC performFetch] executes and FRC.fetchedObjects is set/updated 2) when [tableView reloadData] is called (should at least check the numberOfSectionsInTableView ?)
.H FILE :
#import <UIKit/UIKit.h>
#import <CoreData/CoreData.h>
@interface ChecklistViewController : UIViewController <NSFetchedResultsControllerDelegate,
UITableViewDelegate,
UITableViewDataSource>
{
UIView *sectionsView;
UITableViewController *sectionsTable;
NSFetchedResultsController *sectionsFetchedResultsController;
}
@property (nonatomic, retain) IBOutlet UIView *sectionsView;
@property (nonatomic, retain) IBOutlet UITableViewController *sectionsTable;
@property (nonatomic, retain) NSFetchedResultsController *sectionsFetchedResultsController;
-(void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath;
@end
.M FILE
#import "ChecklistViewController.h"
#import "Inspection.h"
#import "InspectionQuestion.h"
#import "ContextManager.h"
@implementation ChecklistViewController
@synthesize sectionsView;
@synthesize sectionsTable;
@synthesize sectionsFetchedResultsController;
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
//Setup tableviews
self.sectionsTable = [[UITableViewController alloc] init];
self.sectionsTable.view = self.sectionsView;
self.sectionsTable.tableView.dataSource = self;
self.sectionsTable.tableView.delegate = self;
//Fetch sections
NSError *error = nil;
if (self.sectionsFetchedResultsController.fetchedObjects == nil) {
self.sectionsFetchedResultsController.delegate = self;
if (![[self sectionsFetchedResultsController] performFetch:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
}
NSLog(@"fetched results:%@",self.sectionsFetchedResultsController.fetchedObjects);
//For testing delegates
[self.sectionsTable.tableView reloadData];
}
- (void)viewDidUnload
{
[super viewDidUnload];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return YES;
}
#pragma mark -
#pragma mark TableViewDelegate methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
NSInteger count = [[self.sectionsFetchedResultsController sections] count];
if (count == 0) {
count = 1;
}
return count;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSInteger numberOfRows = 0;
if ([[self.sectionsFetchedResultsController sections] count] > 0) {
id <NSFetchedResultsSectionInfo> sectionInfo = [[self.sectionsFetchedResultsController sections] objectAtIndex:section];
numberOfRows = [sectionInfo numberOfObjects];
}
NSLog(@"CheckListViewController::numberOfRowsInSection - numberOfRows:%d", numberOfRows);
return numberOfRows;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// Dequeue or if necessary create a TableViewCell, then set its to the for the current row.
static NSString *cellIdentifier = @"cellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {
// Configure the cell
NSLog(@"CheckListViewController::configureCell - indexPath:%@,", indexPath);
InspectionQuestion *question = [self.sectionsFetchedResultsController objectAtIndexPath:indexPath];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(@"CheckListViewController::didSelectRowAtIndexPath - started");
InspectionQuestion *question = [self.sectionsFetchedResultsController objectAtIndexPath:indexPath];
//[self show: animated:YES];
NSLog(@"CheckListViewController::didSelectRowAtIndexPath - ended");
}
#pragma mark -
#pragma mark FetchedResultsController
- (NSFetchedResultsController *)sectionsFetchedResultsController {
// Set up the fetched results controller if needed.
NSLog(@"ChecklistViewController::sectionsFetchedResultsController - started");
if (sectionsFetchedResultsController == nil) {
NSLog(@"ChecklistViewController::fetchedResultsController - FETCHING new results");
NSManagedObjectContext *managedObjectContext = [[ContextManager sharedContext] managedObjectContext];
// Create the fetch request for the entity.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"InspectionQuestion" inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"sectionId" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:nil
cacheName:nil
// cacheName:@"Root"
];
//aFetchedResultsController.delegate = self;
self.sectionsFetchedResultsController = aFetchedResultsController;
// self.sectionsFetchedResultsController.delegate = self;
/* ARC
[aFetchedResultsController release];
[fetchRequest release];
[sortDescriptor release];
[sortDescriptors release];
*/
}
return sectionsFetchedResultsController;
}
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
// The fetch controller is about to start sending change notifications, so prepare the table view for updates.
if ( controller == self.sectionsFetchedResultsController ) {
[self.sectionsTable.tableView beginUpdates];
}
}
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {
UITableView *tableView;
if ( controller == self.sectionsFetchedResultsController ) {
tableView = self.sectionsTable.tableView;
}
switch(type) {
case NSFetchedResultsChangeInsert:
NSLog(@"ChecklistViewController::didChangeObject - INSERT");
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
NSLog(@"ChecklistViewController::didChangeObject - DELETE");
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate:
NSLog(@"ChecklistViewController::didChangeObject - UPDATE");
[self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
break;
case NSFetchedResultsChangeMove:
NSLog(@"ChecklistViewController::didChangeObject - MOVE");
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {
switch(type) {
case NSFetchedResultsChangeInsert:
[self.sectionsTable.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[self.sectionsTable.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
// The fetch controller has sent all current change notifications, so tell the table view to process all updates.
[self.sectionsTable.tableView endUpdates];
}
@end
Thanks
Upvotes: 0
Views: 1089
Reputation: 861
I found the issue -- the UITableViewController was not properly being added to the view hierarchy
Instead of
- (void)viewDidLoad
{
[super viewDidLoad];
//Setup tableviews
self.sectionsTable = [[UITableViewController alloc] init];
self.sectionsTable.view = self.sectionsView;
self.sectionsTable.tableView.dataSource = self;
self.sectionsTable.tableView.delegate = self;
it should be
- (void)viewDidLoad
{
[super viewDidLoad];
//Setup tableviews
self.sectionsTable = [[UITableViewController alloc] init];
[self.sectionsView addSubview:self.sectionsTable.view];
self.sectionsTable.tableView.dataSource = self;
self.sectionsTable.tableView.delegate = self;
Note: the frame for the sectionsTable.view still needs to be set.
The tableview and FRC delegate methods are now being called and the tableview renders.
Upvotes: 0
Reputation: 7344
try changing UITableViewController
to UITableView
UITableView *sectionsTable;
and make the type your UIViewController
a UITableViewController
@interface ChecklistViewController : UITableViewController <NSFetchedResultsControllerDelegate,
UITableViewDelegate,
UITableViewDataSource>
Upvotes: 1