Переупорядочение основных данных в нескольких разделах - PullRequest
0 голосов
/ 18 августа 2011

В следующем коде переупорядочение строк в 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 ]

1 голос
/ 18 августа 2011

Поскольку ваш массив 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 ... Ifэтот путь ключа не совпадает с указанным первым дескриптором сортировки в fetchRequest, они должны генерировать одинаковые относительные упорядочения.Например, первый дескриптор сортировки в fetchRequest может указывать ключ для постоянного свойства;sectionNameKeyPath может указывать ключ для переходного свойства, полученного из постоянного свойства.

Ваш первичный ключ сортировки - displayOrder, но ваш sectionNameKeyPath - area, и я сомневаюсь, что они производят такой же порядок сортировки.

Обычно плохая практика помещать интерфейсную функцию, например displayOrder, в модель данных.Что произойдет, если у вас несколько столов с разными порядками?Если порядок не является произвольным и не требует сохранения приложением, не создавайте атрибут.

Кроме того, в двух местах кода есть такая конструкция:

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

Хотя синтаксически это допустимо, это всего лишь ошибка, ожидающая своего появления.Если утверждение верно, метод возвращается немедленно.Если false, блок выполняется.Это уродливая, уродливая конструкция, которую легко понять неправильно.Кроме того, вы выдаете недействительный возврат.Компилятор предупредит вас об этом, и вы должны обратить на это внимание.

0 голосов
/ 19 сентября 2014

Re: «объяснение, почему это работает только в первом разделе, а не в других»

Сценарий:

Раздел 1

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

Раздел 2

  • objectAA at indexPath.section = 1, indexPath.row = 0
  • objectBBat indexPath.section = 1, indexPath.row = 1
  • objectCC at indexPath.section = 1, indexPath.row = 2

Когда вы копируете объекты в изменяемый массив, вы«потеря» indexPath.section и ваш массив выглядит следующим образом:

  • objectA с индексом 0
  • objectB с индексом 1
  • objectC с индексом 2
  • objectAA с индексом 3
  • objectBB с индексом 4
  • objectCC с индексом 5

Когда вы удаляете и вставляете объект в 1-й секции, вы вставляете его в неопределенныйxPath.row от 0 до 2 в индексах вашего массива от 0 до 2, что правильно, поэтому он работает

Когда вы удаляете и вставляете объект во 2-й секции, вы все равно вставляете его в indexPath.row от 0 до 2(но indexPath.section 1 уже), но ваш массив не имеет раздела.поэтому он снова вставляется с индексами от 0 до 2, а не с 3 до 5, поэтому он не сортируется правильно

...