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 之类的接口函数放入数据模型中通常是不好的做法。如果您有多个表,所有表都具有不同的顺序,会发生什么?除非顺序是任意的并且应用程序需要保留一些东西,否则不要创建属性。

此外,在代码的两个地方,你有这个结构:

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

虽然在语法上是合法的,但这只是一个等待发生的错误。如果该语句为真,则该方法立即返回。如果为 false,则执行该块。这是一个丑陋、丑陋的结构,很容易被误读。另外,您正在发出无效退货。编译器会警告你,你应该注意它。

于 2011-08-18T19:33:24.477 回答
0

回复:“解释为什么它只适用于第一部分而不适用于其他部分”

设想:

第 1 节

  • indexPath.section = 0 处的 objectA,indexPath.row = 0
  • indexPath.section = 0,indexPath.row = 1 处的 objectB
  • indexPath.section = 0,indexPath.row = 2 处的 objectC

第 2 节

  • indexPath.section = 1 处的 objectAA,indexPath.row = 0
  • indexPath.section = 1 处的 objectBB,indexPath.row = 1
  • indexPath.section = 1,indexPath.row = 2 处的 objectCC

当您将对象复制到可变数组中时,您正在“丢失” indexPath.section 并且您的数组看起来像:

  • 索引 0 处的对象A
  • 索引 1 处的 objectB
  • 索引 2 处的 objectC
  • 索引 3 处的 objectAA
  • 索引 4 处的 objectBB
  • 索引 5 处的 objectCC

当您在第 1 部分中删除并插入一个对象时,您将它在 indexPath.row 从 0 到 2 插入到从 0 到 2 的数组索引中,这是正确的,所以它可以工作

当您在第 2 部分中删除并插入一个对象时,您仍然在 indexPath.row 从 0 到 2 插入它(但 indexPath.section 1 已经),但您的数组没有部分。所以它再次插入从 0 到 2 的索引,而不是 3 到 5,所以它没有正确排序

于 2014-09-19T13:16:36.493 回答