1

FRC を使用して CoreData のセルを並べ替える方法に取り組んでいます。順序属性を使用し、それに応じてこれを更新することを提案する多くの投稿に出くわしました。そのようなコードの 1 つを以下に示します。

新しいオブジェクトを挿入するときに、表示順序を設定し、それに応じてインクリメントする必要があります

これがそのコードです

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

しかし、100 個のアイテムがあり、途中から 1 つのアイテムを削除すると、displayOrder を再計算する必要がありますが、これは実現不可能だと思います。このプロセスを実行する別の方法はありますか

よろしくランジット

4

1 に答える 1

4

なぜインデックス番号を再計算する必要があると思いますか?

項目は、適用した並べ替え順序に従って配置されます。

昇順の並べ替えを指定し、数値を指定すると、正しい並べ替えが行われます。必要ないのは、アイテムの注文に使用する番号と配列内のアイテムのインデックスとの間の直接の対応です。例: 注文番号が

1 2 3 4

次に、それらを取得して並べ替えると、この順序で表示されます。ただし、注文番号が異なる場合でも、同じ順序で表示されます。

1 3 5 7

番号は位置を記録するのではなく、並べ替えにのみ使用されるため、番号がなくても問題ありません。

ここで、インデックスに従って並べ替えられた 4 つのアイテムがあるとします。

1 2 3 4

2番目のアイテムを削除します

1 3 4

アイテムが 1 つ少なくなりましたが、同じ順序のままです。最後にアイテムを追加するとします。

1 3 4 5

ここで、最後にある項目を 3 番目の位置に移動したいとします。ここで、別の質問を自問します。なぜ順序付けインデックスは整数でなければならないのでしょうか? float を使用すると、前の数値と後の数値の中間点として新しいインデックスを簡単に計算できることがわかります。したがって、最後のアイテムを 3 番目の位置に移動した後、順序付けインデックスは次のようになります。

1.0 3.0 3.5 4.0

2番目の位置に数字を追加するのはどうですか。この場合、中点は簡単に計算できます。

1.0 2.0 3.0 3.5 4.0

そう。順序付けインデックスを使用しても問題はありません。整数である必要はないため、アイテムを削除するときに、すべてのインデックスを再度計算する必要はありません。

現在、これらのフロートは不自然に大きくなる可能性がありますが、アプリのダウンタイム中、またはユーザーが少しのセットアップが発生することを期待している更新中に、定期的な再番号付けを実行できます。

于 2012-11-05T11:45:18.003 に答える