2012-04-11 4 views
3

У меня есть объект Tag со строковым свойством tagName. Я пошел, чтобы получить все объекты в этом Entity в NSFetchedResultsController, но я хочу, чтобы Tag с tagName «Главная» был первым объектом. Вот что я делаю сейчас:Сортировка результатов основных данных в NSFetchedResultsController

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 
    NSEntityDescription *entity = [NSEntityDescription 
            entityForName:@"Tag" inManagedObjectContext:appDelegate.managedObjectContext]; 

[fetchRequest setEntity:entity]; 

NSSortDescriptor *lastDescriptor2 = 
[[[NSSortDescriptor alloc] initWithKey:@"tagName" ascending:NO comparator:^NSComparisonResult(NSString* tag1, NSString* tag2) { 
    NSLog(@"compare"); 
    if ([tag1 isEqualToString:@"main"]) return NSOrderedAscending; 
    if ([tag2 isEqualToString:@"main"]) return NSOrderedDescending; 
    return [tag1 compare:tag2]; 
}] autorelease]; 

[fetchRequest setSortDescriptors:[NSArray arrayWithObject:lastDescriptor2]]; 
NSFetchedResultsController *theFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:appDelegate.managedObjectContext sectionNameKeyPath:nil cacheName:nil]; 
self.fetchedResultsController = theFetchedResultsController; 
self.fetchedResultsController.delegate=self; 

if (![[self fetchedResultsController] performFetch:&error]) { 
    NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
} 

Этот код называется в моем viewDidLoad методе, и вызывается только один раз. В первый раз, когда он вызывается, по какой-то причине sortDescriptor здесь не применяется - он просто не вызван (оператор NSLog тоже не отображается). Мои результаты возвращаются исключительно на основе значения BOOL, которое я указываю для ascending - блок игнорируется.

Но когда я ввожу новый объект Tag в MOC и делегат метода NSFetchedResultsController обновлений называется, фактический sortDescriptor будет применяться, и NSLog(@"compare") наконец появляется, но только тогда, когда я делаю обновление объектов! Независимо от того, что я пробовал, я не могу заставить сортировку применить к первоначальной выборке.

Любые идеи вообще?

+0

Mohabitar, вы пробовали использовать стандартный дескриптор сортировки вместо одного с пользовательским компаратором? Я говорю об этом, потому что есть некоторые нечетные неуказанные правила о том, какие действия действительно могут быть применены при извлечении в хранилище. Кроме того, я предлагаю вам изолировать ваше тестирование только от NSFetchRequest. Контроллер результатов добавляет шум. IOW, убедитесь, что выборка работает. Тогда беспокойтесь о его отображении. Andrew – adonoho

+0

Ya все работает правильно с нормальным дескриптором сортировки. Выполняется выборка. Мои результаты даже выбраны в алфавитном порядке с этим дескриптором сортировки выше, поэтому все работает. И я попробовал этот точный дескриптор сортировки по нормальному запросу на выбор без NSFetchedResultsController, и он работал нормально. Это просто NSFetchedResultsController, что дает мне проблемы. – Snowman

ответ

1

Как вы, вероятно, видели в какой-то момент, если предикат, который вы передаете в свой NSFetchRequest, является предикатом блока, ваш запрос на выбор не удастся. Это происходит потому, что CoreData необходимо перевести ваш предикат в SQL, чтобы он мог запускать его в базе данных. В результате предикат никогда не сравнивается с объектами, которые являются результатом запроса на выборку.

То же самое относится к дескрипторам сортировки. Запрос выборки не выполняет сравнение с объектами при выполнении выборки. Он передается как часть SQL.

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