Ranjit
Ranjit

Reputation: 4636

Reorder of cells in CoreData using Fetch ResultsController

I am working on how to reorder cells in CoreData using FRC, I came across many posts which suggest to use a order attribute and update this accordingly, one such code is here below

While inserting New Object I have to set display Order and increment it according

here is the code for it

- (void)insertNewObject
{ 
    Test *test = [NSEntityDescription insertNewObjectForEntityForName:@"Test" inManagedObjectContext:self.managedObjectContext];

 NSManagedObject *lastObject = [self.controller.fetchedObjects lastObject];

float lastObjectDisplayOrder = [[lastObject valueForKey:@"displayOrder"] floatValue];

[test setValue:[NSNumber numberWithDouble:lastObjectDisplayOrder + 1.0] forKey:@"displayOrder"];

}



- (void)tableView:(UITableView *)tableView 
moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath 
      toIndexPath:(NSIndexPath *)destinationIndexPath;
{  
  NSMutableArray *things = [[fetchedResultsController fetchedObjects] mutableCopy];

  // Grab the item we're moving.
  NSManagedObject *thing = [[self fetchedResultsController] objectAtIndexPath:sourceIndexPath];

  // Remove the object we're moving from the array.
  [things removeObject:thing];
  // Now re-insert it at the destination.
  [things insertObject:thing atIndex:[destinationIndexPath row]];

  // All of the objects are now in their correct order. Update each
  // object's displayOrder field by iterating through the array.
  int i = 0;
  for (NSManagedObject *mo in things)
  {
    [mo setValue:[NSNumber numberWithInt:i++] forKey:@"displayOrder"];
  }

  [things release], things = nil;

 // [managedObjectContext save:nil];
     NSError *error = nil;

    if (![managedObjectContext save:&error]) 
    {
        NSString *msg = @"An error occurred when attempting to save your user profile changes.\nThe application needs to quit.";
        NSString *details = [NSString stringWithFormat:@"%@ %s: %@", [self class], _cmd, [error userInfo]];
        NSLog(@"%@\n\nDetails: %@", msg, details);
    }

    // re-do the fetch so that the underlying cache of objects will be sorted
    // correctly

    if (![fetchedResultsController performFetch:&error])
    {
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }
}

But suppose I have 100 items, and I delete any one item from middle then I have to recalculate the displayOrder, which I think is not feasible. Is there any alternative way to do this process

Regards Ranjit

Upvotes: 1

Views: 374

Answers (1)

Abizern
Abizern

Reputation: 150605

Why do you think you need to recalculate the index number?

The items are arranged according to the sort order you apply.

If you supply an ascending sort order, and you supply a number, then you will get the right sorting. What you don't need is a direct correspondance between the number you use to order your items and the index of the item in the array. For example: If your ordering numbers are

1 2 3 4

Then when you fetch them and sort them they will appear in this order. But if the ordering numbers are different, they will still appear in the same order.

1 3 5 7

it doesn't matter that numbers are missing, because they are only used for sorting, not recording a position.

Now, let's imagine you have 4 items sorted according to an index.

1 2 3 4

Now delete the second item

1 3 4

You have 1 less item, but they are still in the same order. Say you add an item to the end:

1 3 4 5

Now imagine you want to move the item at the end to be in the third position. This is where you ask yourself another question: Why does the ordering index have to be an integer? If you use floats, you can see that it is easy to calculate a new index as the mid point between the number before and the number after. So, After moving the item at the end to be in the 3rd position, this is what the ordering indexes will look like:

1.0 3.0 3.5 4.0

How about adding a number in the second position. In this case the midpoint is easy to calculate:

1.0 2.0 3.0 3.5 4.0

So. There is nothing wrong with using an ordering index. It doesn't need to be an integer, so when you delete an item you don't have to go through and calculate all the indexes again.

Now, it is likely that these floats will grow ungainly, but you can run periodic renumberings in your app's downtime, or during updates when users expect a bit of set up to happen.

Upvotes: 4

Related Questions