核心数据在多个部分重新排序

时间:2011-08-18 11:34:00

标签: objective-c core-data sections

在下面的代码中,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

2 个答案:

答案 0 :(得分: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 docs:

  

sectionNameKeyPath ...如果此键路径与此不同   由fetchRequest中的第一个排序描述符指定,它们必须   生成相同的相对排序。例如,第一种   fetchRequest中的描述符可以指定持久性的密钥   属性; sectionNameKeyPath可能指定瞬态的键   属性来自持久属性。

您的主要排序键是displayOrder,但您的sectionNameKeyPath是area,我怀疑它们会产生相同的排序顺序。

将displayOrder等接口函数放入数据模型通常是不好的做法。如果您有多个表,但所有订单都不同,会发生什么?除非排序是任意的并且应用程序需要持久化,否则不要创建属性。

此外,在代码中的两个位置,您有此构造:

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

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

答案 1 :(得分:0)

回复:&#34;解释为什么它只适用于第一部分,而不适用于其他部分&#34;

<强>情境:

第1节

  • objectA在indexPath.section = 0,indexPath.row = 0
  • objectB在indexPath.section = 0,indexPath.row = 1
  • objectC at indexPath.section = 0,indexPath.row = 2

第2节

  • objectAA at indexPath.section = 1,indexPath.row = 0
  • objectBB at indexPath.section = 1,indexPath.row = 1
  • indexCC在indexPath.section = 1,indexPath.row = 2

当您将对象复制到可变数组中时,您将失去&#34;失去&#34; indexPath.section和你的数组看起来像:

  • objectA at index 0
  • indexB at index 1
  • indexC at index 2
  • indexAA at index 3
  • indexBB at index 4
  • indexCC at index 5

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

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