Having Trouble Reading From Core Data - ios

I have an array that the user can add objects to. I have a table view that lists "bad" ingredients the user does not want in their food. They can add these objects in an array, but I don't think Im reading them properly. I know for sure I'm writing properly because I make sure that my code checks for it.
This is how I add objects in Core Data:
-(void)addRow
{
UIAlertView *myAlertView = [[UIAlertView alloc] initWithTitle:#"Add a Bad Ingredient" message:#"Type the name of the ingredient" delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:#"Cancel", nil];
myAlertView.alertViewStyle = UIAlertViewStylePlainTextInput;
[myAlertView show];
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
NSManagedObjectContext *context = [self managedObjectContext];
AllergicIngredient *allergic = [NSEntityDescription insertNewObjectForEntityForName:#"AllergicIngredient" inManagedObjectContext:context];
NSString *enteredString = [[alertView textFieldAtIndex:0] text];
[allergic setValue:enteredString forKey:#"name"];
NSError *error;
if (![context save:&error])
{
NSLog(#"Couldnt find the save %#", error.localizedDescription);
}
else
{
NSLog(#"It saved properly");
}
[badIngredientsArray addObject:enteredString];
NSLog(#"%#", badIngredientsArray);
[self.tableView reloadData];
}
This is how I read from it (Making sure my array is getting Objects from core Data):
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:#"AllergicIngredient"];
badIngredientsArray = [[managedObjectContext executeFetchRequest:fetchRequest error:nil] mutableCopy];
[self.tableView reloadData];
}
I'm struggling with finding the errors in how I get read from it. So far, I'm not given any error messages or SIGABRTS, because the app just crashed when I try to go to the specific page where I'm fetching the data.

I see you're using a UITableView with Core Data.
Given the context, why don't you use an NSFetchResultsController?
If you use that, you will then be able to perform the following:
#pragma mark - Fetched Results Controller Section
- (NSFetchedResultsController *)fetchedResultsController {
if (_fetchedResultsController) {
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:[MyMO description]
inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
// Specify how the fetched objects should be sorted
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#""
ascending:YES
selector:#selector(localizedStandardCompare:)];
[fetchRequest setSortDescriptors:[NSArray arrayWithObjects:sortDescriptor, nil]];
[fetchRequest setFetchBatchSize:20];
NSError *error = nil;
NSArray *fetchedObjects = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
if (fetchedObjects == nil) {
NSLog(#"Error Fetching: %#", error);
}
_fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:#"masterCache"];
_fetchedResultsController.delegate = self;
return _fetchedResultsController;
}
- (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 arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate: {
Person *changedPerson = [self.fetchedResultsController objectAtIndexPath:indexPath];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.textLabel.text = changedPerson.birthName;
}
break;
case NSFetchedResultsChangeMove:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
default:
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;
default:
break;
}
}
And UITableView methods:
- (void)viewDidLoad
{
[super viewDidLoad];
NSError *error = nil;
if (![self.fetchedResultsController performFetch:&error]) {
NSLog(#"Error while fetching: %#", error);
abort();
}
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return [self.fetchedResultsController.sections count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
id <NSFetchedResultsSectionInfo> sectionInfo = self.fetchedResultsController.sections[section];
return [sectionInfo numberOfObjects];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
MyMo *mo = [self.fetchedResultsController objectAtIndexPath:indexPath];
// Configure the cell...
return cell;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
return [self.fetchedResultsController.sections[section]name];
}
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
NSManagedObjectContext *context = self.managedObjectContext;
MyMo *mo = [self.fetchedResultsController objectAtIndexPath:indexPath];
[context deleteObject:mo];
NSError *error = nil;
if (![context save:&error]) {
NSLog(#"Error saving: %#", error);
}
}
}

Related

UITableView not updating with Core Data

I have a Single View Application. It uses a ViewController embedded in a NavigationController. I have one UITextField and a UITableView added to the ViewController.
My model is extremely simple. It has two entities:
itemname
createdAt
I am able to create a new item without issue. When I look at the SQLite database, it do see the actual data being inserted correctly. My issue right now is that I cannot seem to figure out why the data is not being displayed in my UITableView.
ViewController.m
#import "ViewController.h"
#interface ViewController () <NSFetchedResultsControllerDelegate>
#property (strong) NSMutableArray *items;
#property(nonatomic, strong) IBOutlet UITableView *tableView;
#property (strong, nonatomic) NSFetchedResultsController *fetchedResultsController;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
NSError *error;
if (![[self fetchedResultsController] performFetch:&error]) {
// Update to handle the error appropriately.
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
exit(-1); // Fail
}
}
- (NSFetchedResultsController *)fetchedResultsController {
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Item" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:#"itemname" ascending:NO];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];
[fetchRequest setFetchBatchSize:20];
NSFetchedResultsController *theFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:#"ItemCache"];
self.fetchedResultsController = theFetchedResultsController;
self.fetchedResultsController.delegate = self;
return _fetchedResultsController;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (NSManagedObjectContext *)managedObjectContext
{
NSManagedObjectContext *context = nil;
id delegate = [[UIApplication sharedApplication] delegate];
if ([delegate performSelector:#selector(managedObjectContext)]) {
context = [delegate managedObjectContext];
}
return context;
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
// Fetch the devices from persistent data store
NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:#"Item"];
self.items = [[managedObjectContext executeFetchRequest:fetchRequest error:nil] mutableCopy];
[self.tableView reloadData];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return self.items.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell...
NSManagedObject *item = [self.items objectAtIndex:indexPath.row];
[cell.textLabel setText:[NSString stringWithFormat:#"%#", [item valueForKey:#"itemname"]]];
[cell.detailTextLabel setText:[item valueForKey:#"itemname"]];
return cell;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
NSManagedObjectContext *context = [self managedObjectContext];
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete object from database
[context deleteObject:[self.items objectAtIndex:indexPath.row]];
NSError *error = nil;
if (![context save:&error]) {
NSLog(#"Can't Delete! %# %#", error, [error localizedDescription]);
return;
}
// Remove device from table view
[self.items removeObjectAtIndex:indexPath.row];
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
}
- (IBAction)cancel:(id)sender {
//implement action here for cancel button to dismiss keyboard
}
- (IBAction)saveItem:(id)sender {
NSManagedObjectContext *context = [self managedObjectContext];
// Create a new managed object
NSManagedObject *newItem = [NSEntityDescription insertNewObjectForEntityForName:#"Item" inManagedObjectContext:context];
[newItem setValue:self.itemTextField.text forKey:#"itemname"];
NSLog(#"Creating new item");
NSError *error = nil;
// Save the object to persistent store
if (![context save:&error]) {
NSLog(#"Can't Save! %# %#", error, [error localizedDescription]);
}
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"updateItem"]) {
NSManagedObject *selectedItem = [self.items objectAtIndex:[[self.tableView indexPathForSelectedRow] row]];
ViewController *destViewController = segue.destinationViewController;
destViewController.itemTextField = selectedItem;
}
}
EDIT
Ive gone in and added my NSFetchedResultsController protocols.
- (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;
}
}
I seem to be getting an error on this line:
case NSFetchedResultsChangeUpdate:
[self configureCell:[tableView cellForRowAtIndexPath:indexPath]
atIndexPath:indexPath];
break;
Does this need a datasource declared before tableView? If the UITableView is connected to the File Owner's datasource, should this be self?
I think it should actually look like this:
case NSFetchedResultsChangeUpdate:
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
break;
You need to implement NSFetchedResultsControllerDelegate to handle changes to results, such as when entities are inserted into the store.
The delegate will update the tableView's model.
At the least, you simply could reload the table when your delegate was called.
inside perform fetch block, implement [tableView reloadData];

NSFetchedResultsController attempt to insert row 1 into section 0, but there are only 0 rows in section 0 after the update with userInfo (null)

i use NSFetchedResultsController with UITableViewController.
i successfully add new ocject to core data in separated view,
ParseStarterProjectAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [appDelegate managedObjectContext];
NSManagedObject *newWorkout;
newWorkout = [NSEntityDescription insertNewObjectForEntityForName:#"Workouts" inManagedObjectContext:context];
[newWorkout setValue:_workOutType forKey:#"type"];
[newWorkout setValue:_boostDate forKey:#"date"];
[newWorkout setValue:_workoutText forKey:#"text"];
[newWorkout setValue:_trainerLabelOutlet.text forKey:#"text"];
NSError *error;
if (![context save:&error]) {
NSLog(#"Whoops, couldn't save: %#", [error localizedDescription]);
}else{
NSLog(#"saved to core data");
}
but i get this error :
An exception was caught from the delegate of NSFetchedResultsController during a call to -controllerDidChangeContent:. attempt to insert row 1 into section 0, but there are only 0 rows in section 0 after the update with userInfo (null)
the code in the UITableViewController:
- (NSManagedObjectContext *)managedObjectContext {
NSManagedObjectContext *context = nil;
id delegate = [[UIApplication sharedApplication] delegate];
if ([delegate performSelector:#selector(managedObjectContext)]) {
context = [delegate managedObjectContext];
}
return context;
}
- (NSFetchedResultsController *)fetchedResultsController {
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
entityForName:#"Workouts" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:#"date" ascending:NO];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];
[fetchRequest setFetchBatchSize:20];
NSFetchedResultsController *theFetchedResultsController =
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil
cacheName:#"Root"];
self.fetchedResultsController = theFetchedResultsController;
_fetchedResultsController.delegate = self;
return _fetchedResultsController;
}
- (void)viewDidLoad
{
[super viewDidLoad];
NSError *error;
if (![[self fetchedResultsController] performFetch:&error]) {
// Update to handle the error appropriately.
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
exit(-1); // Fail
}
}
- (void)viewDidUnload {
self.fetchedResultsController = nil;
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return [[self.fetchedResultsController sections] count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
id sectionInfo = [[_fetchedResultsController sections] objectAtIndex:section];
return [sectionInfo numberOfObjects];
}
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {
WorkoutObject *workout = [_fetchedResultsController objectAtIndexPath:indexPath];
cell.textLabel.text = workout.text;
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyy-MM-dd HH:mm"];
NSString *dateString = [dateFormatter stringFromDate:workout.date];
cell.detailTextLabel.text = dateString;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
CustomTableViewCell *cell =[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// Set up the cell...
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
- (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 )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];
}
Does anyone know what the problem is?
i try to figure it out myself for the past 2 days but i incapable to.
thanks
I just had the same issue - in my case it turned out to be because the table view data source and delegates hadn't been assigned to the view controller on the storyboard in the outlets section of the attributes inspector. Hence numberOfRowsForSection and numberOfSectionsInTableView were not being called.

update CoreData Object not working correct

I'm new to iOS development/CoreData and have searched for an answer to my specific problem, but haven't found one yet.
I have a TableView with some Objects from my database. Each of the objects has an attribute "name". If I open the details view of one of the objects and go back to the tableView with the "back" Button everything works fine. It also works if I do no changes to the "name" TextField and press the "done" Button to get back to my tableView. As soon as I do some changes in the "name" TextField I get this error:
Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (9) must be equal to the number of rows contained in that section before the update (9), plus or minus the number of rows inserted or deleted from that section (0 inserted, 1 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).
Why is there an object being deleted?
Here is the code of my DetailsStaticTableViewController.m:
#import "WeinStaticTableViewController.h"
#import "Wein.h"
#import "JSMToolBox.h"
#interface WeinStaticTableViewController ()
#end
#implementation WeinStaticTableViewController
#synthesize nameTextView;
#synthesize landTextView;
#synthesize herstellerTextView;
#synthesize wein = _wein;
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
if (self.wein != nil) {
self.nameTextView.text = self.wein.name;
}
}
- (void) viewDidDisappear:(BOOL)animated
{
[[JSMCoreDataHelper managedObjectContext] rollback];
[super viewDidDisappear:animated];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
[self setNameTextView:nil];
[self setLandTextView:nil];
[self setHerstellerTextView:nil];
self.wein = nil;
}
- (IBAction)barButtonItemDonePressed:(id)sender
{
NSLog(#"%s", __PRETTY_FUNCTION__);
if (self.wein != nil) {
self.wein.name = self.nameTextView.text;
[JSMCoreDataHelper saveManagedObjectContext:[JSMCoreDataHelper managedObjectContext]];
}
[self.navigationController popViewControllerAnimated:YES];
}
#end
Here is the code of my JSMCoreDataHelper.m:
#import "JSMCoreDataHelper.h"
#implementation JSMCoreDataHelper
+ (NSString*) directoryForDatabaseFilename
{
return [NSHomeDirectory() stringByAppendingString:#"/Library/Private Documents"];
}
+ (NSString*) databaseFileName
{
return #"database.sqlite";
}
+ (NSManagedObjectContext*) managedObjectContext
{
static NSManagedObjectContext *managedObjectContext;
if (managedObjectContext != nil) {
return managedObjectContext;
}
NSError *error;
// Verzeichnis unter dem das Datenbank-File abgespeichert werden soll, wird neu erzeugt, falls es noch nicht existiert.
[[NSFileManager defaultManager] createDirectoryAtPath:[JSMCoreDataHelper directoryForDatabaseFilename] withIntermediateDirectories:YES attributes:nil error:&error];
if (error) {
NSLog(#"Fehler: %#", error.localizedDescription);
return nil;
}
NSString *path = [NSString stringWithFormat:#"%#/%#", [JSMCoreDataHelper directoryForDatabaseFilename], [JSMCoreDataHelper databaseFileName]];
NSURL *url = [NSURL fileURLWithPath:path];
NSManagedObjectModel *managedModel = [NSManagedObjectModel mergedModelFromBundles:nil];
NSPersistentStoreCoordinator *storeCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:managedModel];
if (! [storeCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:url options:nil error:&error]) {
NSLog(#"Fehler: %#", error.localizedDescription);
return nil;
}
managedObjectContext = [[NSManagedObjectContext alloc] init];
managedObjectContext.persistentStoreCoordinator = storeCoordinator;
return managedObjectContext;
}
+ (id) insertManagedObjectOfClass: (Class) aClass inManagedObjectContext: (NSManagedObjectContext*) managedObjectContext
{
NSManagedObject *managedObject = [NSEntityDescription insertNewObjectForEntityForName:NSStringFromClass(aClass) inManagedObjectContext:managedObjectContext];
return managedObject;
}
+ (BOOL) saveManagedObjectContext: (NSManagedObjectContext*) managedObjectContext
{
NSError *error;
if (! [managedObjectContext save:&error]) {
NSLog(#"Fehler: %#", error.localizedDescription);
return NO;
}
return YES;
}
+ (NSArray*) fetchEntitiesForClass: (Class) aClass withPredicate: (NSPredicate*) predicate inManagedObjectContext: (NSManagedObjectContext*) managedObjectContext
{
NSError *error;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:NSStringFromClass(aClass) inManagedObjectContext:managedObjectContext];
fetchRequest.entity = entityDescription;
fetchRequest.predicate = predicate;
NSArray *items = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
if (error) {
NSLog(#"Fehler: %#", error.localizedDescription);
return nil;
}
return items;
}
+ (BOOL) performFetchOnFetchedResultsController: (NSFetchedResultsController*) fetchedResultsController
{
NSError *error;
if (! [fetchedResultsController performFetch:&error]) {
NSLog(#"Fehler: %#", error.localizedDescription);
return NO;
}
return YES;
}
#end
And finally the numberOfSections and numberOfRowsInSection of my MainTableViewController:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return [[self.fetchedResultsController sections] count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [[[self.fetchedResultsController sections] objectAtIndex:section] numberOfObjects];
}
Any clue could help...thank you !
Heres my code using a NSFetchedResultsController, this works fine with your code for managing CoreData.
Hope this helps.
#import "Person.h"
#import "mainViewController.h"
#import "JSMCoreDataHelper.h"
#import "staticInfoViewController.h"
#implementation mainViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Load From CoreData
NSError *error;
if (![[self fetchedResultsController] performFetch:&error]) {
// Update to handle the error appropriately.
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
exit(-1); // Fail
}
}
#pragma mark - TableView DataSource
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return [[self.fetchedResultsController sections] count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [[[self.fetchedResultsController sections] objectAtIndex:section] numberOfObjects];
}
- (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];
}
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
Person *p = [_fetchedResultsController objectAtIndexPath:indexPath];
cell.textLabel.text = [NSString stringWithFormat:#"Name: %#", p.name];
}
#pragma mark - TableView Delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
staticInfoViewController *info = [[staticInfoViewController alloc] initWithNibName:#"staticInfoViewController" bundle:[NSBundle mainBundle]];
info.currentPerson = [_fetchedResultsController objectAtIndexPath:indexPath];
[self.navigationController pushViewController:info animated:YES];
}
#pragma mark - Set NSFetchedResultsController
- (NSFetchedResultsController *)fetchedResultsController {
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
entityForName:#"Person" inManagedObjectContext:[JSMCoreDataHelper managedObjectContext]];
[fetchRequest setEntity:entity];
NSSortDescriptor *sort = [[NSSortDescriptor alloc]
initWithKey:#"name" ascending:YES];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];
[fetchRequest setFetchBatchSize:20];
NSFetchedResultsController *theFetchedResultsController =
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:[JSMCoreDataHelper managedObjectContext] sectionNameKeyPath:nil
cacheName:#"cache"];
self.fetchedResultsController = theFetchedResultsController;
_fetchedResultsController.delegate = self;
return _fetchedResultsController;
}
#pragma mark - NSFetchedResultsController Delegate
- (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 )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];
}
#end
you have wrong number of data in UI and in core data. the row count dosnt match in UI and core data. you have daleted one row but UI/fetchresultcontroller does not know about and tries to read it from the database. either refetch after changes or implement the fetch result controller delegate:
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath;
- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type;
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller;
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller;
do not forget to set fetch result controller to self.( viel spass )

TableView or FetchedResultController Error - getting a blank row

I have a simple app that create some object. Everything works fine but if i press the add button that open a detailViewController and there i will press cancel instead of saving it goes back to de mainTableView but it show a blank row, if i open the sql file there's no empty object so it should be an issue between the fetchedResultController and tableView loading it.
i know its not the best way to add an Object because in my add action i create an entity even if the user wont save. Yet it shouldnt show the blank row. Why is that happening? How to fix?
This is my code:
IngredietnViewController.m
#import "IngredientsTableViewController.h"
#interface IngredientsTableViewController ()
#end
#implementation IngredientsTableViewController
#synthesize managedObjectContext = _managedObjectContext;
#synthesize fetchedResultsController = _fetchedResultsController;
#synthesize ingredient = _ingredient;
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = #"Ingredients";
UIBarButtonItem *addButton = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:#selector(addIngredient)];
self.navigationItem.rightBarButtonItem = addButton;
self.navigationItem.leftBarButtonItem = self.editButtonItem;
self.tableView.tableFooterView = [[UIView alloc] init];
}
#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][section];
NSLog(#"%lu", (unsigned long)[sectionInfo numberOfObjects]);
return [sectionInfo numberOfObjects];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
// Configure the cell...
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
- (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]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
}
}
#pragma mark - Action
-(void)addIngredient{
DetailIngredientViewController *detailIngredientVC =[[DetailIngredientViewController alloc]initWithNibName:#"DetailIngredientViewController" bundle:nil];
detailIngredientVC.delegate = self;
self.ingredient = [NSEntityDescription insertNewObjectForEntityForName:#"Ingredient" inManagedObjectContext:self.managedObjectContext];
detailIngredientVC.detailIngredient = self.ingredient;
[self.navigationController pushViewController:detailIngredientVC animated:YES];
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{}
#pragma mark - Fetched Result
- (NSFetchedResultsController *)fetchedResultsController
{
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Ingredient" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
[fetchRequest setFetchBatchSize:20];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"name" ascending:NO];
NSArray *sortDescriptors = #[sortDescriptor];
[fetchRequest setSortDescriptors:sortDescriptors];
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]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
return _fetchedResultsController;
}
- (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];
}
#pragma mark - configureCell:
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
Ingredient *object = [self.fetchedResultsController objectAtIndexPath:indexPath];
cell.textLabel.text = object.name ;
cell.detailTextLabel.text = object.rappresentation;
}
-(void)controller:(UIViewController *)controller didSaveIngredient:(Ingredient *)DetailIngredient{
NSLog(#"INGREDIENT SAVED");
NSError *error = nil;
if (![self.managedObjectContext save:&error]){
NSLog(#"Error %# %#", error, [error userInfo]);
}
[self.tableView reloadData];
}
#end
DeataiIngredientlViewController.m
#implementation DetailIngredientViewController
#synthesize tfNameIngredient, detailIngredient, tvDescription;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
UIBarButtonItem *saveButton = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemSave target:self action:#selector(saveIngredient)];
self.navigationItem.rightBarButtonItem = saveButton;
}
-(void)saveIngredient{
if ([self verifyIngredient] == YES){
detailIngredient.name = tfNameIngredient.text;
detailIngredient.rappresentation = tvDescription.text;
[self.delegate controller:self didSaveIngredient:detailIngredient];
[self.navigationController popToRootViewControllerAnimated:YES];
}
else{
NSLog(#"SBALLATA");
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error" message:#"The Name and description are empty" delegate:self cancelButtonTitle:#"Back" otherButtonTitles:nil, nil];
[alert show];
}
}
-(BOOL)verifyIngredient{
if ([tfNameIngredient.text length] < 4 || [tvDescription.text length] < 4 ){
return NO;
}
else{
return YES;
}
}
#end
Your blank row corresponds to Ingredient NSManagedObject you created in addIngredient.
Even though you didn't save: the NSManagedObjectContext it still exists and is picked up by your NSFetchedResultsController.
When the user cancels the add you need to delete it. Perhaps add a controller:(UIViewController *)controller didCancelAddIngredient: method to your delegate?
ALSO, in controller:(UIViewController *)controller didSaveIngredient: you don't need to reloadData on your UITableView, that's what all that NSFetchedResultsControllerDelegate code is there to do for you.

Core data table view duplicating cells when re launch application

I have a storyboard with core data project with 1 entity named "Password" and 4 string attributes, the data is connected to a table view with fecthedResultsController and the sections are set by one of the attributes calld "type".
When I launch my app every thing is o.k, I can add, update and delete and nothing is wrong.
Even when I go out of the app to the home screen and come back nothing happens.
The problem is when I close the app from the multitasking menu and re launch it, I get empty cells in the same amount of good ones.
they are grouped at the top with no section.
What am I doing wrong?
insertViewController.m
-(IBAction)insertPassword:(id)sender
{
NSInteger row;
NSString*subTypeSelectd=[[NSString alloc]init];
row = [pickerSubjects selectedRowInComponent:0];
subTypeSelectd = [arrSubSubjects objectAtIndex:row];
NSInteger row2;
NSString*TypeSelectd=[[NSString alloc]init];
row2 = [pickerSubjects selectedRowInComponent:1];
TypeSelectd = [arrSubject objectAtIndex:row2];
// self.insertPassword.desc=self.txtDesc.text;
// self.insertPassword.userName=self.txtUserName.text;
// self.insertPassword.password=self.txtPassword.text;
// self.insertPassword.type=TypeSelectd;
// self.insertPassword.subType=subTypeSelectd;
// NSLog(#"insertPassword");
// [self.delegete addPasswordViewControllerDidSave];
AppDelegate *delegate = [UIApplication sharedApplication].delegate;
NSManagedObjectContext *addViewcontrollerLocalContext = delegate.managedObjectContext;
NSManagedObject*password=[NSEntityDescription insertNewObjectForEntityForName:#"Password" inManagedObjectContext:addViewcontrollerLocalContext];
[password setValue:self.txtDesc.text forKey:#"desc"];
[password setValue:self.txtUserName.text forKey:#"userName"];
[password setValue:self.txtPassword.text forKey:#"password"];
[password setValue:subTypeSelectd forKey:#"subType"];
[password setValue:TypeSelectd forKey:#"type"];
NSError*error;
if(![addViewcontrollerLocalContext save:&error])
NSLog(#"input %#",error);
else NSLog(#"saved");
[self.navigationController popViewControllerAnimated:YES];
}
and the mainViewController.m
-(void)addPasswordViewControllerDidSave
{
NSManagedObjectContext*context=self.manageObjectContext;
NSError*error;
if(![context save:&error])
NSLog(#"error : %#",error);
NSLog(#"addPasswordViewControllerDidSave");
[self.navigationController popViewControllerAnimated:YES];
}
-(void)addPasswordViewControllerDidDelete:(Password *)passwordToDelete
{
NSLog(#"B");
NSManagedObjectContext*context=self.manageObjectContext;
[context deleteObject:passwordToDelete];
[self.navigationController popViewControllerAnimated:YES];
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([[segue identifier]isEqualToString:#"addPassword"])
{
insertViewController*ipvc=(insertViewController*)[segue destinationViewController];
Password*p=(Password*)[NSEntityDescription insertNewObjectForEntityForName:#"Password" inManagedObjectContext:[self manageObjectContext]];
// ipvc.delegete=self;
ipvc.insertPassword=p;
}
if([[segue identifier]isEqualToString:#"updatePassword"])
{
updateViewController*uvc=(updateViewController*)[segue destinationViewController];
NSIndexPath*indexPath=[self.tableView indexPathForSelectedRow];
Password*p=[self.fecthedResultsController objectAtIndexPath:indexPath];
uvc.updatePassword=p;
}
}
//-------------------------------------------------------------table------------
-(NSFetchedResultsController*)fecthedResultsController
{
if(fecthedResultsController!=nil)
return fecthedResultsController;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Password"
inManagedObjectContext:[self manageObjectContext]];
[fetchRequest setEntity:entity];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"type" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
fecthedResultsController=[[NSFetchedResultsController
alloc]initWithFetchRequest:fetchRequest managedObjectContext:[self manageObjectContext]
sectionNameKeyPath:#"type" cacheName:nil];
fecthedResultsController.delegate=self;
return fecthedResultsController;
}
-(void)controllerWillChangeContent:(NSFetchedResultsController *)controller
{
[self.tableView beginUpdates];
[self.tableView reloadData];
}
-(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 arrayWithObject:newIndexPath]
withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:[tableview deleteRowsAtIndexPaths:[NSArray
arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate:{
Password*p=[self.fecthedResultsController objectAtIndexPath:indexPath];
UITableViewCell*cell=[tableview cellForRowAtIndexPath:indexPath];
cell.textLabel.text=p.userName;
cell.detailTextLabel.text=p.password;
// cell.imageView.image=[UIImage imageWithData: p.photodata];
}
break;
case NSFetchedResultsChangeMove:
[tableview deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
[tableview insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
withRowAnimation:UITableViewRowAnimationFade];
break;
default:
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];
default:
break;
} }
-(NSString*)tableView:(UITableView *)tableView titleForHeaderInSection:
(NSInteger)section
{
return [[[self.fecthedResultsController sections]objectAtIndex:section]name];
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:
(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
NSManagedObjectContext*context=[self manageObjectContext];
Password*passwordToDelete=[self.fecthedResultsController objectAtIndexPath:indexPath];
[context deleteObject:passwordToDelete];
NSError*error;
if(![context save:&error])
NSLog(#"error");
} }
//-------------------------------------------------------------table-end-----------
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
-(void)viewWillApear
{
}
- (void)viewDidLoad
{
[super viewDidLoad];
NSError*error;
if(![[self fecthedResultsController]performFetch:&error])
{
NSLog(#"ERROR");
abort();
}
// 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)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
//#warning Potentially incomplete method implementation.
// Return the number of sections.
NSLog(#"%i",[[self.fecthedResultsController sections]count]);
return [[self.fecthedResultsController sections]count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
//#warning Incomplete method implementation.
// Return the number of rows in the section.
id<NSFetchedResultsSectionInfo>secInfo=[[self.fecthedResultsController
sections]objectAtIndex:section];
return [secInfo numberOfObjects];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell...
NSLog(#"cell");
Password*p=[self.fecthedResultsController objectAtIndexPath:indexPath];
cell.textLabel.text=p.userName;
cell.detailTextLabel.text=p.password;
// if(p.photodata!=nil)
// cell.imageView.image=[UIImage imageWithData: p.photodata];
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 60;
}
You have a typo in this line in your cellForRowAtIndexPath method:
it should be fetched ResultsController:
Password*p=[self.fecthedResultsController objectAtIndexPath:indexPath];
and again in your numberOfSectionInTableView:
NSLog(#"%i",[[self.fecthedResultsController sections]count]);
return [[self.fecthedResultsController sections]count];
and possibly in other methods.

Resources