I have followed this tutorial from Dennis Roberson on core data (https://www.youtube.com/watch?v=ZoTAKAjEIFM). Everything builds fine and i've set up my model etc correctly but it does not seem to save, even the NSLog in -(void)saveAndDismiss method does not display in the console? Have anyone encountered this or might be able to help me?
My CoreViewController.m
#import "CoreViewController.h"
#import "AppDelegate.h"
#interface CoreViewController ()
#property (nonatomic,strong) NSManagedObjectContext *managedObjectContext;
#end
#implementation CoreViewController
-(NSManagedObjectContext*)managedObjectContext{
return [(AppDelegate*)[[UIApplication sharedApplication]delegate]managedObjectContext];
}
-(void)cancelAndDismiss{
[self.managedObjectContext rollback];
[self.navigationController popViewControllerAnimated:YES];
}
-(void)saveAndDismiss{
NSError *error = nil;
if ([self.managedObjectContext hasChanges]) {
if (![self.managedObjectContext save:&error]) {
NSLog(#"Save Failed: %#",[error localizedDescription]);
} else {
NSLog(#"Save Succeeded");
}
}
[self.navigationController popViewControllerAnimated:YES];
}
#end
my personTableViewController.h
#import <UIKit/UIKit.h>
#import "Person.h"
#interface personTableViewController : UITableViewController <NSFetchedResultsControllerDelegate>
#property (nonatomic,strong)Person *person;
#end
my PersonTableViewController.m
#import "personTableViewController.h"
#import "AppDelegate.h"
#import "personViewController.h"
#interface personTableViewController ()
#property (nonatomic,strong)NSManagedObjectContext *managedObjectContext;
#property (nonatomic,strong)NSFetchedResultsController *fetchedResultsController;
#end
#implementation personTableViewController
-(NSManagedObjectContext*)managedObjectContext{
return [(AppDelegate*)[[UIApplication sharedApplication]delegate]managedObjectContext];
}
- (void)viewDidLoad {
[super viewDidLoad];
NSError *error = nil;
if (![[self fetchedResultsController]performFetch:&error]) {
NSLog(#"Error! %#", error);
abort();
}
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [[self.fetchedResultsController sections]count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
id<NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections]objectAtIndex:section];
return [sectionInfo numberOfObjects];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
// Configure the cell...
Person *person = [self.fetchedResultsController objectAtIndexPath:indexPath];
cell.textLabel.text = person.personName;
[self.tableView reloadData];
return cell;
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([[segue identifier]isEqualToString:#"addPerson"]) {
UINavigationController *navigationController = segue.destinationViewController;
personViewController *addPersonViewController = (personViewController*)
navigationController.topViewController;
Person *addPerson = [NSEntityDescription insertNewObjectForEntityForName:#"Person" inManagedObjectContext:[self managedObjectContext]];
addPersonViewController.addPerson = addPerson;
}
}
#pragma mark - Fetched Results Controller Section
-(NSFetchedResultsController*)fetchedResultsController{
if (_fetchedResultsController !=nil) {
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc]init];
NSManagedObjectContext *context = [self managedObjectContext];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Person" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc]initWithKey:#"personName" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc]initWithObjects:sortDescriptor, nil];
fetchRequest.sortDescriptors = sortDescriptors;
_fetchedResultsController = [[NSFetchedResultsController alloc]initWithFetchRequest:fetchRequest managedObjectContext:context sectionNameKeyPath:nil cacheName:nil];
_fetchedResultsController.delegate = self;
return _fetchedResultsController;
}
#pragma mark - Fetched Results Controller Delegates
-(void)controllerWillChangeContent:(NSFetchedResultsController *)controller{
[self.tableView beginUpdates];
}
-(void)controllerDidChangeContent:(NSFetchedResultsController *)controller{
[self.tableView endUpdates];
}
-(void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath{
UITableView *tableView = self.tableView;
switch (type) {
case NSFetchedResultsChangeInsert:
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObjects:newIndexPath,nil] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath,nil] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate: {
Person *changePerson = [self.fetchedResultsController objectAtIndexPath:indexPath];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.textLabel.text = changePerson.personName;
}
break;
case NSFetchedResultsChangeMove:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath,nil] withRowAnimation:UITableViewRowAnimationFade];
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObjects:newIndexPath,nil] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
-(void)controller:(NSFetchedResultsController *)controller didChangeSection:(id<NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {
switch (type) {
case NSFetchedResultsChangeInsert:
[self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete :
[self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeMove:
NSLog(#"A table item was moved");
break;
case NSFetchedResultsChangeUpdate:
NSLog(#"A table item was updated");
break;
}
}
#end
In personViewController.h
#import <UIKit/UIKit.h>
#import "CoreViewController.h"
#import "Person.h"
#interface personViewController : CoreViewController
- (IBAction)savePressed:(id)sender;
- (IBAction)cancelPressed:(id)sender;
#property (strong, nonatomic) IBOutlet UITextField *personNameTextField;
#property (strong,nonatomic) Person *addPerson;
#end
And my personViewController.m (add person view controller with text fields)
#import "personViewController.h"
#import "AppDelegate.h"
#import "CoreViewController.h"
#interface personViewController ()
#end
#implementation personViewController
#synthesize addPerson;
#synthesize personNameTextField;
- (IBAction)savePressed:(id)sender {
addPerson.personName = personNameTextField.text;
[super saveAndDismiss];
}
- (IBAction)cancelPressed:(id)sender {
[super cancelAndDismiss];
}
#end
Sorry for so much code, just i am very stuck and run out of ideas
Related
I'm implementing a UITableView with NSFetchedResultsController.
# D5ProductViewController.h
#interface D5ProductViewController : D5ViewControllerAbstract <UITableViewDataSource, UITableViewDelegate, NSFetchedResultsControllerDelegate>
#property (nonatomic, strong) NSManagedObjectContext *managedObjectContext;
#property (nonatomic, strong) D5Product *product;
#property (weak, nonatomic) IBOutlet UITableView *tableView;
- (IBAction)addVariantTapped:(id)sender;
#end
# D5ProductViewController.m
#interface D5ProductViewController ()
#property (nonatomic, retain) NSFetchedResultsController *fetchedResultsController;
#end
#implementation D5ProductViewController
- (void)viewLoad {
NSError *error;
[self.fetcedResultsController performFetch:&error];
if (error) {
[self.alerts showError:[error localizedDescription]
:#"Error"];
}
}
#pragma mark - Properties
#synthesize managedObjectContext; // The context is passed from a parent view.
#synthesize fetchedResultsController = _fetchedResultsController;
- (NSFetchedResultsController *)fetchedResultsController {
if (_fetchedResultsController) {
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:#"Variant"
inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entityDescription];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"price"
ascending:NO];
[fetchRequest setSortDescriptors:#[sortDescriptor]];
NSString *predicateString = [NSString stringWithFormat:#"productId = '%#' AND isMaster = 0", self.product.identifier];
NSPredicate *predicate = [NSPredicate predicateWithFormat:predicateString];
[fetchRequest setPredicate:predicate];
[fetchRequest setReturnsObjectsAsFaults:NO];
_fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:self.managedObjectContext
sectionNameKeyPath:nil
cacheName:nil];
_fetchedResultsController.delegate = self;
return _fetchedResultsController;
}
#pragma mark - NSFetchedResultsControllerDelegate
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
[self.tableView beginUpdates];
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
[self.tableView endUpdates];
[self.tableView reloadData];
}
- (void)controller:(NSFetchedResultsController *)controller
didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath
forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath {
switch (type) {
case NSFetchedResultsChangeInsert:
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate:
[self configureCell:(D5VariantTableViewCell *)[self.tableView cellForRowAtIndexPath:indexPath]
withObject:(D5Variant *)[controller objectAtIndexPath:indexPath]];
break;
case NSFetchedResultsChangeMove:
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)configureCell:(D5VariantTableViewCell *)cell
withObject:(D5Variant *)variant {
cell.variant = variant;
}
#pragma mark - UITableViewDataSourceDelegate
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section {
id sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:section];
return [sectionInfo numberOfObjects];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [self.fetchedResultsController.sections count];
}
#pragma mark - UITableViewDelegate
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
D5VariantTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:D5VariantCellReusableIdentifier
forIndexPath:indexPath];
D5Variant *variant = [self.fetchedResultsController objectAtIndexPath:indexPath];
cell.variant = variant;
cell.managedObjectContext = self.managedObjectContext;
return cell;
}
- (IBAction)addVariantTapped:(id)sender {
NSEntityDescription *variantEntityDescription = [NSEntityDescription entityForName:#"Variant"
inManagedObjectContext:self.managedObjectContext];
D5Variant *variant = [[D5Variant alloc] initWithEntity:variantEntityDescription
insertIntoManagedObjectContext:self.managedObjectContext];
variant.productId = self.product.identifier;
variant.price = [self.product.master price];
variant.weight = [self.product.master weight];
[variant markAsInserted];
NSError *error;
[self.fetchedResultsController performFetch:&error];
if (error) {
NSLog(#"%#", error);
}
[self.tableView reloadData];
}
#end
If I understand correctly, having implemented NSFetchedResultsController's controller:didChangeObject:atIndexPath:forChangeType:newIndexPath will cause UITableView to ask for a cell for the inserted row, which is configured with the object at the given indexPath from the fetchedResultsController.
The thing is that controller:didChangeObject...newIndexPath is never called when a new object is inserted in the managedObjectContext.
What am I missing? Do I need to call managedObjectContext's save method and then [self.tableView reloadData].
Thanks in advance!
Silly me, I forgot to set the UITableView's delegate:
The viewDidLoad method, besides setting the bindings, was just performing the fetch. Adding self.tableView.delegate = self; fixed the problem, BUT, isn't it enough setting the dataSource outlet in the IB? Which I already did. Why did I need to set the UITableView's delegate manually? In the case of the NSFetchedResultsController it needs to be set manually, but isn't it the purpose of the UITableView object having that outlet to just wire it up to the delegate object?
Anyways, setting self.tableView.delegate = self; fixed the problem.
Just a caveat, this is my first ever question, be gentle with me.
I had a UITableViewController that conforms to the NSFetchedResultsControllerDelegate protocol. This all works perfectly. I want to change that to a UIViewController to be able to add more to the view than just the tableview. I created the tableView property and set the delegate and datasource. Everything works fine except that the FRC delegate methods are not called and the table is not updated. The inserts, edits, and deletes are being stored to the database, but the table is not updating when I change something in the context.
All the code is the basic template code for using a fetched results controller. When it sets the delegate in the line:
aFetchedResultsController.delegate = self;
It should be setting the delegate correctly, but it is not. Again, the only change I make is to remove the word Table from UITableViewController. It works with the UITableViewController but not the UIViewController. I have researched this extensively but have not found an answer.
Thanks.
Here's some code:
#import <UIKit/UIKit.h>
#import <CoreData/CoreData.h>
.
.
.
#class NowWhatDetailViewController;
#class Event;
#interface NowWhatMasterViewController : UITableViewController <NSFetchedResultsControllerDelegate, ChangeDateViewControllerDelgate, EditEventViewControllerDelgate, PasswordViewControllerDelegate,
UITableViewDelegate, UITableViewDataSource> {
NSMutableArray *saveButtonItems;
IBOutlet UILabel *nextEventLabel;
IBOutlet UILabel *timeToNextEventLabel;
}
#property (strong, nonatomic) NowWhatDetailViewController *detailViewController;
#property (strong, nonatomic) NSFetchedResultsController *fetchedResultsController;
#property (strong, nonatomic) NSManagedObjectContext *managedObjectContext;
#property (nonatomic, weak) id <ChangeDateViewControllerDelgate> delegate;
#property (nonatomic, retain) IBOutlet UITableView *tableView;
.
.
.
#end
And the important sections of NowWhatMasterViewController.m
#import "NowWhatMasterViewController.h"
#interface NowWhatMasterViewController () {
}
#end
#implementation NowWhatMasterViewController {
Event *lastEditedEvent;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self performFetch];
[[self.splitViewController.viewControllers lastObject] topViewController];
self.detailViewController.viewNSDate = self.viewNSDate;
self.detailViewController.viewDate = self.viewDate;
self.detailViewController.viewSchedule = self.viewSchedule;
self.detailViewController.managedObjectContext = self.managedObjectContext;
self.detailViewController.fetchedResultsControllerDetail = self.fetchedResultsController;
[self.detailViewController updateDetailView];
// show the bottom toolbar
[self.navigationController setToolbarHidden:NO];
saveButtonItems = [self.toolbarItems mutableCopy];
nextEventLabel.text = #"next event";
timeToNextEventLabel.text = #"starts in ## minutes";
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
self.fetchedResultsController = nil;
}
- (void)viewDidUnload {
self.fetchedResultsController = nil;
}
#pragma mark - Table View
/*
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [dayEvents count];
}
*/
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath
{
Event *event = [self.fetchedResultsController objectAtIndexPath:indexPath];
[self performSegueWithIdentifier:#"EditEvent" sender:event];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
id <NSFetchedResultsSectionInfo> sectionInfo = [self.fetchedResultsController sections][section];
return [sectionInfo numberOfObjects];
//return [dayEvents count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"EventCell"];
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
if (_isLocked) {
return NO;
} else {
return YES;
}
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];
[context deleteObject:[self.fetchedResultsController objectAtIndexPath:indexPath]];
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();
}
}
}
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
// The table view should not be re-orderable.
return NO;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
Event *event = [self.fetchedResultsController objectAtIndexPath:indexPath];
[event toggleChecked];
[self configureCheckmarkForCell:cell withEvent:event];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
// this updates the detail controller when a row is selected. Not sure we want to do that
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
NSManagedObject *object = [[self fetchedResultsController] objectAtIndexPath:indexPath];
self.detailViewController.detailItem = object;
}
}
#pragma mark - Fetched results controller
- (NSFetchedResultsController *)fetchedResultsController
{
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
NSLog(#"the fetched results controller is getting the events for %#", self.viewNSDate);
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:#"eventNSDate" ascending:YES];
NSArray *sortDescriptors = #[sortDescriptor];
[fetchRequest setSortDescriptors:sortDescriptors];
// setup the predicate to return just the wanted date and schedule
NSPredicate *requestPredicate = [NSPredicate predicateWithFormat:[NSString stringWithFormat:#"(eventDate like '%#') AND (schedule.scheduleName like '%#')", [Event returnDateString:self.viewNSDate], self.viewSchedule.scheduleName]];
[fetchRequest setPredicate:requestPredicate];
// Clear out any previous cache
[NSFetchedResultsController deleteCacheWithName:#"Master"];
// 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();
}
// manually set the delegate?
return _fetchedResultsController;
}
- (void)performFetch
{
NSError *error;
if (![self.fetchedResultsController performFetch:&error]) {
//FATAL_CORE_DATA_ERROR(error);
NSLog(#"database error");
return;
}
}
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
{
[self.tableView beginUpdates];
}
- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo
atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type
{
switch(type) {
case NSFetchedResultsChangeInsert:
[self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath
{
UITableView *tableView = self.tableView;
switch(type) {
case NSFetchedResultsChangeInsert:
[tableView insertRowsAtIndexPaths:#[newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate:
[self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
break;
case NSFetchedResultsChangeMove:
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView insertRowsAtIndexPaths:#[newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
[self.tableView endUpdates];
}
I'm trying to create a UITable view to display a datasource saved through core data. I would like each row to be named after one of the attributes (in my case the name of the song). I have successfully made tables that display arrays but not saved data. I think that i need to import the list in tagsviewcontroller and put some code into the numberofrowsinsection and cellforrowatindex but I couldn't get my head around the apple doc's.
Any help would be great and if you need me to post more of the code i can do that.
I am fairly new to this, i've created a Tableviewcontroller using a standard xcode template as shown below.
// TagsViewController.h
#import <UIKit/UIKit.h>
#interface TagsViewController : UITableViewController <UITableViewDataSource, UITableViewDelegate, NSFetchedResultsControllerDelegatee>
#property (nonatomic, strong) NSManagedObjectContext *context;
#end
and the .m file
#import "TagsViewController.h"
#import "Music.h"
#interface TagsViewController ()
#property (nonatomic, strong) NSFetchedResultsController *fetchedResultsController;
#end
#implementation TagsViewController
#synthesize fetchedResultsController=_fetchedResultsController, context=_context;
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Uncomment the following line to preserve selection between presentations.
// self.clearsSelectionOnViewWillAppear = NO;
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
- (void)viewWillAppear
{
[self.tableView reloadData];
}
- (void)viewDidUnload
{
// Release any properties that are loaded in viewDidLoad or can be recreated lazily.
self.fetchedResultsController = nil;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [[self.fetchedResultsController sections] count];
}
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
// Configure the cell to show the book's title
Music *music = [self.fetchedResultsController objectAtIndexPath:indexPath];
cell.textLabel.text = music.name;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:section];
return [sectionInfo numberOfObjects];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// Configure the cell.
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
/*
Returns the fetched results controller. Creates and configures the controller if necessary.
*/
- (NSFetchedResultsController *)fetchedResultsController
{
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
// Create and configure a fetch request with the Book entity.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Music" inManagedObjectContext:self.context];
[fetchRequest setEntity:entity];
// Create the sort descriptors array.
// NSSortDescriptor *authorDescriptor = [[NSSortDescriptor alloc] initWithKey:#"author" ascending:YES];
// NSSortDescriptor *titleDescriptor = [[NSSortDescriptor alloc] initWithKey:#"title" ascending:YES];
// NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:authorDescriptor, titleDescriptor, nil];
// [fetchRequest setSortDescriptors:sortDescriptors];
// Create and initialize the fetch results controller.
_fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.context sectionNameKeyPath:#"artist" cacheName:#"Root"];
_fetchedResultsController.delegate = self;
// Memory management.
return _fetchedResultsController;
}
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
{
// The fetch controller is about to start sending change notifications, so prepare the table view for updates.
[self.tableView beginUpdates];
}
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath
{
UITableView *tableView = self.tableView;
switch(type) {
case NSFetchedResultsChangeInsert:
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate:
[self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
break;
case NSFetchedResultsChangeMove:
[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.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[self.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.tableView endUpdates];
}
I know that i'll have to import certain files. My database is called music.xcmodeld and has its own music.h and m file.
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#interface Music : NSManagedObject
#property (nonatomic, retain) NSString * name;
#property (nonatomic, retain) NSString * artist;
#property (nonatomic, retain) NSString * album;
#end
with .m file
#import "Music.h"
#implementation Music
#dynamic name;
#dynamic artist;
#dynamic album;
#end
you can use NSFetchedResultsController a sample code is here
http://developer.apple.com/library/ios/#samplecode/CoreDataBooks/Listings/Classes_RootViewController_m.html#//apple_ref/doc/uid/DTS40008405-Classes_RootViewController_m-DontLinkElementID_14
There is no difference if you display from array or core data. Just query core data when the view controller is loading and add the results to an array. Then you know what to do with an array of data.
In cell for row at index you would pull each object from the array and add whatever you want from it to the cell
- (void)viewDidLoad
{
[super viewDidLoad];
arrData = [[NSMutabaleArray alloc]init];
NSManagedObjectContext *context = //Get it from AppDelegate
NSFetchRequest *request = [[NSFetchRequest alloc]initWithEntityName:#"Music"];
NSError *error = nil;
arrData = [[context executeFetchRequest:request error:&error]mutablecopy];
if (error != nil) {
//Deal with failure
}
else {
//Deal with success
}
// Uncomment the following line to preserve selection between presentations.
// self.clearsSelectionOnViewWillAppear = NO;
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
For Table View
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return arrData.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
Music *obj = [arrData objectAtindex:indexPath.row];
cell.textLabel.text = obj. name;
// Configure the cell...
return cell;
}
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
try changing UITableViewController to UITableView
UITableView *sectionsTable;
and make the type your UIViewController a UITableViewController
#interface ChecklistViewController : UITableViewController <NSFetchedResultsControllerDelegate,
UITableViewDelegate,
UITableViewDataSource>
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.
This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
happy holidays!
so, Im grappling with coredata!, now I have info showing in a viewController in a table, but when I put the table in a second viewController called from the first, I get>
entityForName: could not locate an NSManagedObjectModel for entity name 'Contacts''
even though the code was working as mentioned before(in just one view), what shall I do?
thank you so much!
The little test project is
Here the project saves a contact (verified in a SQLite manager) but when taken to another view to check the contacts in a table it crashes, the part of the showing something of a db in a table inside the UIViewcontroller is working code also but in the main view not yet from this called xib, thanks
here the code, (show.h, the view loaded from the main view..)
#import <UIKit/UIKit.h>
#interface ShowViewController : UIViewController
<UITableViewDelegate, UITableViewDataSource, NSFetchedResultsControllerDelegate>
{
NSFetchedResultsController *_fetchedResultsController;
NSManagedObjectContext *_context;
UITableView *tableView;}
#property (nonatomic, retain) NSFetchedResultsController *fetchedResultsController;
#property (nonatomic, retain) NSManagedObjectContext *context;
#property (nonatomic, retain) IBOutlet UITableView *tableView;
-(IBAction) btnStart:(id) sender;
#end
(show.m)
#import "ShowViewController.h"
#import "Contacts.h"
#implementation ShowViewController
#synthesize context = _context;
#synthesize fetchedResultsController = _fetchedResultsController;
#synthesize tableView;
-(IBAction) btnStart:(id) sender{
initWithNibName:#"StartViewController" bundle:nil];
[UIView beginAnimations:#"flipping view" context:nil];
[UIView setAnimationDuration:1];
[UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
[UIView setAnimationTransition: UIViewAnimationTransitionCurlUp
forView:self.view.superview cache:YES];
[self.view removeFromSuperview];
[UIView commitAnimations];
}
- (NSFetchedResultsController *)fetchedResultsController {
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Contacts" inManagedObjectContext:_context];
[fetchRequest setEntity:entity];
//NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:#"details.closeDate" ascending:NO];
//[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];
[fetchRequest setFetchBatchSize:20];
NSFetchedResultsController *theFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:_context sectionNameKeyPath:nil cacheName:#"Root"];
self.fetchedResultsController = theFetchedResultsController;
_fetchedResultsController.delegate = self;
[fetchRequest release];
[theFetchedResultsController release];
return _fetchedResultsController;
}
- (void)viewDidLoad {
[super viewDidLoad];
/*array = [[NSMutableArray alloc] init];
[array addObject:#"Sports"];
[array addObject:#"Entertainment"];
[array addObject:#"Art"];
[array addObject:#"Technology"];*/
NSError *error;
if (![[self fetchedResultsController] performFetch:&error]) {
// Update to handle the error appropriately.
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
exit(-1); // Fail
}
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
self.fetchedResultsController = nil;
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
id <NSFetchedResultsSectionInfo> sectionInfo = [[_fetchedResultsController sections] objectAtIndex:section];
return [sectionInfo numberOfObjects];
//return [array count];
//return [[fetchedResultsController sections] count];
}
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {
Contacts *info = [_fetchedResultsController objectAtIndexPath:indexPath];
cell.textLabel.text = info.name;
//cell.detailTextLabel.text = [NSString stringWithFormat:#"%#, %#", info.city, info.state];
}
//---insert individual row into the table view---
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
//---try to get a reusable cell---
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
//---create new cell if no reusable cell is available---
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
- (BOOL)shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation)interfaceOrientation {
// Overriden to allow any orientation.
return YES;
}
- (void)dealloc {
self.fetchedResultsController = nil;
self.context = nil;
[super dealloc];
}
#pragma mark NSFetchedResultsControllerDelegate methods
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
// The fetch controller is about to start sending change notifications, so prepare the table view for updates.
[self.tableView beginUpdates];
}
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType: (NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {
UITableView *tableView = self.tableView;
switch(type) {
case NSFetchedResultsChangeInsert:
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate:
[self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
break;
case NSFetchedResultsChangeMove:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
// Reloading the section inserts a new row and ensures that titles are updated appropriately.
[tableView reloadSections:[NSIndexSet indexSetWithIndex:newIndexPath.section] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType: (NSFetchedResultsChangeType)type {
switch(type) {
case NSFetchedResultsChangeInsert:
[self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
// The fetch controller has sent all current change notifications, so tell the table view to process all updates.
[self.tableView endUpdates];
}
#end
I've had this before, make sure your NSManagedObject is actually Contacts, check the spelling and check the case - usually typo