0

次のコードでは、UITableView の行の並べ替えは最初のセクションでのみ機能します。最初のセクション以外のセクションで行を並べ替えた後、ビューが再表示されると、行は元の順序に戻ります。すべてのセクションで並べ替えを機能させるのを手伝ってくれる人はいますか?

- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath;   
    userDrivenDataModelChange = YES;   
    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:@"displayOrder1"];  
    }   
    [things release], things = nil;   
    [__managedObjectContext save:nil];
    userDrivenDataModelChange = NO;
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return [[self.fetchedResultsController sections] count];  
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:section];
    return [sectionInfo numberOfObjects];
}

- (NSFetchedResultsController *)fetchedResultsController
{
    if (__fetchedResultsController != nil)
    {
       return __fetchedResultsController;
    }
    // Edit the entity name as appropriate.
    NSManagedObjectContext *context = [self managedObjectContext];
     NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
     [fetchRequest setEntity:[NSEntityDescription entityForName:@"Client" inManagedObjectContext:context]];
    [fetchRequest setFetchBatchSize:20];  
    // Edit the sort key as appropriate.
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"displayOrder1" ascending:YES];
     NSSortDescriptor *sortDescriptor2 = [[NSSortDescriptor alloc] initWithKey:@"area" ascending:YES];
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor2 ,sortDescriptor ,nil];
    [fetchRequest setSortDescriptors:sortDescriptors];
    [sortDescriptor release];
    [sortDescriptor2 release];
    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"area" cacheName:@"Root"];
    aFetchedResultsController.delegate = self;
    self.fetchedResultsController = aFetchedResultsController;
    [aFetchedResultsController release];
    [fetchRequest release];
    [sortDescriptors release];
     NSError *error = nil;
     if (![self.fetchedResultsController performFetch:&error])
    {
         NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
         abort();
     }
    return __fetchedResultsController;
}   

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
{
    sectionInsertCount = 0; 
    if (userDrivenDataModelChange)return; {
        [self.tableView beginUpdates];      
    }
}

- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo  
           atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type
{
    if (userDrivenDataModelChange)return;{
     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
{
    if (userDrivenDataModelChange)return; {
      UITableView *aTableView = self.tableView;
      switch(type)
        {           
            case NSFetchedResultsChangeInsert:
                [aTableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
                break;
            case NSFetchedResultsChangeDelete:
                [aTableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
                break;
            case NSFetchedResultsChangeUpdate:
                [self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
                break;
            case NSFetchedResultsChangeMove:
                [aTableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
                [aTableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]withRowAnimation:UITableViewRowAnimationFade];
                break;
        }
    }
}

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
    if (userDrivenDataModelChange) return;
    [self.tableView endUpdates];
}

- (void)saveContext {
    NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];
    NSError *error = nil;
    if (![context save:&error]) {
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }
}    
@end
4

2 に答える 2

1

あなたのthings配列はフェッチされた結果コントローラの変更可能なコピーであるため、fetchedObjectsあなたが行う操作はthingsどれも に結果をもたらしませんfetchedObjects

すべての変更はフェッチされた結果コントローラーのdidChange...メソッドで発生するため、手動の変更のみが表示されます。

編集:

あなたの問題はここにあります:

NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"displayOrder1" ascending:YES];
 NSSortDescriptor *sortDescriptor2 = [[NSSortDescriptor alloc] initWithKey:@"area" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor2 ,sortDescriptor ,nil];
[fetchRequest setSortDescriptors:sortDescriptors];
[sortDescriptor release];
[sortDescriptor2 release];
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"area" cacheName:@"Root"];

NSFetchedResultsController ドキュメントから:

sectionNameKeyPath ... このキー パスが fetchRequest の最初の並べ替え記述子によって指定されたものと同じでない場合、それらは同じ相対順序を生成する必要があります。たとえば、fetchRequest の最初のソート記述子は、永続プロパティのキーを指定する場合があります。sectionNameKeyPath は、永続プロパティから派生した一時プロパティのキーを指定する場合があります。

あなたのプライマリソートキーはですdisplayOrderが、あなたの sectionNameKeyPath はarea同じソート順を生成するとは思えません。

通常、displayOrder などのインターフェイス関数をデータ モデルに配置することはお勧めできません。複数のテーブルがあり、すべて順序が異なる場合はどうなりますか? 順序付けが任意であり、アプリが保持する必要があるものでない限り、属性を作成しないでください。

また、コード内の 2 か所に、次の構造があります。

if (userDrivenDataModelChange)return;{
  //...
}

構文的には合法ですが、これは発生するのを待っている単なるバグです。ステートメントが true の場合、メソッドはすぐに戻ります。false の場合、ブロックが実行されます。それは、読み間違えやすい醜い、醜い構造です。さらに、無効な返品を発行しています。コンパイラはこれについて警告するので、注意を払う必要があります。

于 2011-08-18T19:33:24.477 に答える
0

Re: 「最初のセクションでのみ機能し、他のセクションでは機能しない理由の説明」

シナリオ:

セクション 1

  • indexPath.section = 0、indexPath.row = 0 の objectA
  • indexPath.section = 0、indexPath.row = 1 の objectB
  • indexPath.section = 0、indexPath.row = 2 の objectC

第2節

  • indexPath.section = 1、indexPath.row = 0 の objectAA
  • indexPath.section = 1、indexPath.row = 1 の objectBB
  • indexPath.section = 1、indexPath.row = 2 の objectCC

オブジェクトを可変配列にコピーすると、indexPath.section が「失われ」、配列は次のようになります。

  • インデックス 0 の objectA
  • インデックス 1 の objectB
  • インデックス 2 の objectC
  • インデックス 3 の objectAA
  • インデックス 4 の objectBB
  • インデックス 5 の objectCC

最初のセクションでオブジェクトを削除して挿入すると、0 から 2 の indexPath.row に挿入され、0 から 2 の配列インデックスに挿入されます。これは正しいので動作します

2 番目のセクションでオブジェクトを削除して挿入すると、indexPath.row に 0 から 2 まで挿入されますが (ただし、indexPath.section 1 は既に挿入されています)、配列にはセクションがありません。そのため、3 から 5 ではなく 0 から 2 のインデックスに再度挿入されるため、正しくソートされません。

于 2014-09-19T13:16:36.493 に答える