1

what i am trying to do to display only 10 item inside UITableView From Core Data that was easy using [fetchRequest setFetchLimit:10]; but after insertion of the 11th item the first element should not longer be visible inside UITableView and the total number of element should be always 10 i already made many researches about this topic i just found only Get Selected index of UITableView so what i need to to get the index of the row to check wether is larger then 10 delete the 9th element here is the full code needed:

#import "ReservationHistoryTableViewController.h"
#import "CoreData.h"
#import "ReservationEntity.h"
#import "EntryCell.h"
#import "DetailedHistoryViewController.h"
@interface ReservationHistoryTableViewController () <NSFetchedResultsControllerDelegate>


@property (strong, nonatomic) NSFetchedResultsController *fetchedResultController ;

@end

@implementation ReservationHistoryTableViewController

- (IBAction)refresh:(id)sender {

    [self getAllReservationHistory];
    [sender endRefreshing];

}






- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *cellIdentifier =  @"Cell";
    EntryCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
    ReservationEntity *reservationEntry  = [self.fetchedResultController objectAtIndexPath:indexPath];
    [cell configureCellForEntry:reservationEntry];

    return cell;
}







-(NSFetchRequest *) entryListFetchRequest {
    NSFetchRequest *fetchRequest  = [NSFetchRequest fetchRequestWithEntityName:@"Reservations"];
    [fetchRequest setFetchLimit:10];
    [self.tableView reloadData];
    fetchRequest.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"reservationID" ascending:NO]];
    return fetchRequest;

}


// this method is used to fetch the data //
-(NSFetchedResultsController *) fetchedResultController {
    if(_fetchedResultController != nil)
        return _fetchedResultController;
    CoreData *coreDataStack = [CoreData defaultStack];
    NSFetchRequest *fechtRequest = [self entryListFetchRequest];
    _fetchedResultController = [[NSFetchedResultsController alloc] initWithFetchRequest:fechtRequest managedObjectContext:coreDataStack.managedObjectContext sectionNameKeyPath:nil cacheName:nil];
    _fetchedResultController.delegate = self;
    return _fetchedResultController;

}




-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if([segue.identifier isEqualToString:@"details"])
    {
        UITableViewCell *cell = sender;
        NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
        UINavigationController *naviagationController = segue.destinationViewController;
        DetailedHistoryViewController *detailedHisotryViewController = (DetailedHistoryViewController *) naviagationController.topViewController;
        detailedHisotryViewController.entry = [self.fetchedResultController objectAtIndexPath:indexPath];
    }
}




-(void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath
{
    switch (type) {
        case NSFetchedResultsChangeInsert:

//            NSIndexPath *selectedIndexPath = [self. indexPathForSelectedRow];



            if(newIndexPath.section > 10)
            {
                [self.tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
                [self.tableView deleteRowsAtIndexPaths:@[@(9)] withRowAnimation:UITableViewRowAnimationAutomatic];
// even i try if(newIndexPath.row) i could not reach my target // 

            }


            else
            {
                [self.tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
            }

            break;
        default:
            break;
    }
}
Community
  • 1
  • 1
Zakaria Darwish
  • 358
  • 5
  • 22

1 Answers1

2

You are going in wrong direction. NSIndexPath is the one to identify rows and sections, but you are using CoreData and you should not complicate your life doing this type of logic on your own.

The proper solution will be to implement NSFetchedResultsController according to Apple guidelines (you can copy & paste that):

- (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];
}

For deleting the object you should do:

[coreDataStack.managedObjectContext deleteObject:object];

For inserting object:

[coreDataStack.managedObjectContext insertObject:object];

You can also just insert the object - and if it falls into NSFetchedResultsController NSFetchRequest terms - it will be refetched automatically for you and your view will get informed through delegate methods that I pasted above.

Grzegorz Krukowski
  • 18,081
  • 5
  • 50
  • 71
  • how i can know that the number of elements are 10 inside the tableView ? – Zakaria Darwish Aug 11 '15 at 07:38
  • NSFetchedResultsController will take are of that. It keeps it results synced during all those insert/delete operations - if it should refetch because something got inserted - it will do that automatically and inform you with delegates. You just need to make sure that the object you are inserting will actually fall into NSFetchRequest ordering and limit terms - in your case set proper reservationID. – Grzegorz Krukowski Aug 11 '15 at 07:40
  • i just mention a breakPoint on : case NSFetchedResultsChangeMove: [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; break; i notice that this case never occurs – Zakaria Darwish Aug 11 '15 at 07:53
  • If you don't delete objects which are part of your results set - it won't – Grzegorz Krukowski Aug 11 '15 at 08:00
  • and forget to tell you that when fetching the data from core data i am able to getting the last ten records and thats what i want but when i am inserting a new row and the items are 10 inside the UITableView the last item should be deleted and the new one should be inserted let`s take this example 10 9 8 7 6 5 4 3 2 1 and when 11 inserted it should be like that 11 10 9 8 7 6 5 4 3 2 sorry for my bad language in english i think now its much clearer for you thanks in advance – Zakaria Darwish Aug 11 '15 at 08:01
  • the delete process should be automatically done after inserting the 11th element inside the UITableView – Zakaria Darwish Aug 11 '15 at 08:02
  • So you should delete the one of 10 objects and insert a new one, or while inserting a new one, make sure it's gonna be a part of result by using proper ordering and assigning proper order value for it. – Grzegorz Krukowski Aug 11 '15 at 08:04
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/86674/discussion-between-zakaria-darwish-and-grzegorz-krukowski). – Zakaria Darwish Aug 11 '15 at 08:04
  • i just found the solution that match my preferences using numberOfRowsInSection:(NSInteger*) – Zakaria Darwish Aug 11 '15 at 08:57
  • Ok sorry I was afk for a while. Cool that you found a way ! Still using the pasted code for NSFetchedResultsController is the way to go :) – Grzegorz Krukowski Aug 11 '15 at 09:07