8

В настоящее время я пытаюсь заполнить UITableView в моем проекте из Core Data с помощью NSFetchedResultsController. Я использую пользовательский поиск с компаратором (хотя я также попробовал селектор и имел идентичную проблему):NSFetchedResultsController custom sort не получает вызов

if (fetchedResultsController != nil) { 
     return fetchedResultsController; 
    } 

    /* 
    Set up the fetched results controller. 
    */ 
    // Create the fetch request for the entity. 
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 
    // Edit the entity name as appropriate. 
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Object" inManagedObjectContext:self.managedObjectContext]; 
    [fetchRequest setEntity:entity]; 

    // Set the batch size to a suitable number. 
    [fetchRequest setFetchBatchSize:20]; 
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"objectName" ascending:YES comparator:^(id s1, id s2) { 
      NSLog(@"Comparator"); 
     //custom compare here with print statement 
    }]; 
    NSLog(@"Sort Descriptor Set"); 
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil]; 
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Object" inManagedObjectContext:self.managedObjectContext]; 
    [fetchRequest setEntity:entity]; 
    [fetchRequest setSortDescriptors:sortDescriptors]; 

    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"firstLetterOfObject" cacheName:@"Objects"]; 
    [aFetchedResultsController release]; 
    [fetchRequest release]; 
    [sortDescriptor release]; 
    [sortDescriptors release]; 
    if (![fetchedResultsController performFetch:&error]) { 
     NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
     abort(); 
    } 

    return fetchedResultsController; 

Когда я вхожу на эту вкладку, я вошел по всей программе и обнаружил, что NSFetchedResultsController делает даже не вводить блок компаратора при извлечении. Вместо этого он сортирует его с помощью некоторого метода сортировки по умолчанию.

Если я удалю и добавлю объект с именем объекта, однако он затем войдет в блок компаратора и правильно отсортирует таблицу.

Почему NSFetchedResultsController не сортирует с использованием компаратора до изменения модели управляемого объекта?

Примечания: Я попытался также отключить кеширование и/или выполнить выборку в viewDidLoad :, но кажется, что сколько раз я извлекаю, не имеет значения, но когда. По какой-то причине он использует мою сортировку только после того, как объектная модель была изменена.

ответ

8

Есть несколько вещей, Я могу думать. Во-первых, хотя это может и не быть вашей проблемой, вы не можете сортировать по временным свойствам. Но более вероятно, что при сортировке в модели, поддерживаемой хранилищем SQL, компаратор получает «скомпилированный» запрос SQL, и не все функции Objective-C доступны. В этом случае вам нужно отсортировать память после выполнения выборки.

EDIT: См. Это doc, в частности раздел Fetch Predicates and Sort Descriptors.

+1

Они не временные свойства, но ваше другое предложение определенно похоже, что это может быть проблемой. Единственная проблема заключается в том, что я полагаюсь на контрольный контролер, чтобы предоставить имена разделов и т. Д. В виде таблицы, поэтому сортировка в памяти каждый раз будет сложной (я думаю). Как вы порекомендовали бы об этом? И еще мой вопрос: почему блок-компаратор работает после изменения объектной модели? Спасибо! –

+0

На самом деле, более общая проблема заключается в том, что я реализую разделы в своем представлении таблицы вместе с индексом раздела. Я помещаю любой объект, начиная с номера в разделе «123» (это работает), но я хочу, чтобы этот раздел был внизу, как iPod. Согласно приложениям Apple, цифры должны быть последним вариантом в sectionIndex (я использую UILocalizedIndexedCollation для генерации индексов раздела). Однако, как представляется, нет способа получить разделы, чтобы числа были последними. Вы знаете более надежный способ сделать это, чем обычную сортировку? –

+2

Просто догадаться, но я думаю, что блок компаратора работает после того, как объектная модель была изменена, потому что график уже находится в памяти. Но это всего лишь предположение. Я считаю, что сортировка вручную, как мне кажется, заключается в подклассе NSArrayController, поэтому вы потеряете преимущества NSFetchedResultsController. Но, как вы говорите, проблема с корнем заключается в том, что вы хотите сортировать числа в нижней части.Я бы сказал, создавая свойство сортировки на ваших объектах и ​​использую это, но я не сделал достаточной выборочной сортировки, используя дескрипторы сортировки. – Don

0

Извините, но вы пропустили окончательный принести часть в ваш фрагмент кода ?:

NSError *error; 
BOOL success = [aFetchedResultsController performFetch:&error]; 

Не забудьте выпустить запрос тоже:

[fetchRequest release]; 
+0

Нет, я просто не включил его в фрагмент. Я включил весь метод, если это станет более ясным. –

1

Я вижу ту же проблему и способ ее обойти - это изменить объект, сохранить изменения, а затем восстановить его исходное значение и снова сохранить.

// try to force an update for correct initial sorting bug 
NSInteger count = [self.fetchedResultsController.sections count]; 
if (count > 0) { 
    id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:0]; 
    count = [sectionInfo numberOfObjects]; 
    if (count > 0) { 
     NSManagedObject *obj = [self.fetchedResultsController objectAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; 
     NSString *name = [obj valueForKey:@"name"]; 
     [obj setValue:@"X" forKey:@"name"]; 
     // Save the context. 
     [self saveContext]; 
     [obj setValue:name forKey:@"name"]; 
     // Save the context. 
     [self saveContext]; 
    } 
}