Question

I've got a more or less basic Master Detail app. I've followed this tutorial to get familiar with Core Data, and now I'm trying reorder my cells on my Master TVC. Everything is working fine, including the successful reordering of my cells. However, when I dig down and view one of the detail VCs, I return to the original, alphabetized ordering. I believe it has something to do with the NSSortDescriptor "sortDescriptor" that was included in the tutorial. I am not sure how to remove it, or how to give it different characteristics. Any help is appreciated. Below is my NSFetchedResultsController method.

-(NSFetchedResultsController*) fetchedResultsController {

    if (_fetchedResultsController != nil) {
        return _fetchedResultsController;
    }

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];

    NSManagedObjectContext *context = [self managedObjectContext];

    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Top" inManagedObjectContext:context];

    [fetchRequest setEntity:entity];

    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"topName" 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;
}

EDIT: After much research over the past few days, I'm realizing it's more of an issue with my moveRowAtIndexPath method. Anyone have any suggestions or recommendations of working with Core Data and the ability to reorder cells? Also, does this require custom tableviewcell class?

Was it helpful?

Solution

Your table view is sorted based on a name. Given that the names are fixed, if you reorder cells 'by hand' and then return to the table view, the sorting based on the name is reestablished.

To get what you want you'll need to add a field to your Core Data model called something like sortIndex. You then sort the table with a sortDescriptor based on sortIndex; you can initialize sortIndex to the creation order. When the User reorders cells through the UI, you'll also change the sortIndex for all the impacted cells/managed-objects. Then, since sortIndex is part of the Core Data model, when the User ends and restarts your App, their preferred sorting will be reestablished.

Sometimes, for modeling reasons, you don't want to include a sortIndex directly in some managed object. For example, a Person has first and last names but not a sortIndex (in fact). You can create an association, perhaps a DisplayPreferences managed object, with a one-to-one mapping between a Person and a DisplayPreferences and having a sortIndex in DisplayPreferences.

OTHER TIPS

A few things you need to check here:

  1. You need to actually perform the fetch the first time by calling performFetch: on the NSFetchedResultsController. Either do this in the getter method or it should be done in viewDidLoad.
  2. Have you implemented the required NSFetchedResultsControllerDelegate methods properly? That includes controller:didChangeObject:atIndexPath:forChangeType:newIndexPath:, controller:didChangeSection:atIndex:forChangeType: and controllerDidChangeContent:. The code is all boilerplate but you need to make sure it is there.
  3. What do your UITableViewDatasource methods look like? Make sure the sections and row counts look like this:

    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
    {
        return [[[self fetchedResultsController] sections] count];
    }
    
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
    {
        id <NSFetchedResultsSectionInfo> sectionInfo = [self.fetchedResultsController sections][section];
        return [sectionInfo numberOfObjects];
    }  
    
  4. Make sure you are using the indexPath to grab your object in the tableView:cellForRowAtIndexPath: method. It should look something like this:

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"myCellIdentifier"];
        NSManagedObject *object = [self.fetchedResultsController objectAtIndexPath:indexPath];
        cell.textLabel.text = rowPackage.title;
    
        return cell;
    }
    
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top