NSSortDescriptor с произвольной сортировкой - PullRequest
4 голосов
/ 25 ноября 2011

Я не могу понять, как выполнять произвольную сортировку с помощью NSSortDescriptor.

Я хочу сделать что-то вроде этого:

NSArray *sortAlgorithm = [NSArray arrayWithObjects:@"@", @"#", @"!", @"&", @"r", @"a", nil];

NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" 
                                                               ascending:YES 
                                                              comparator:
    ^(id obj1, id obj2) {
        NSComparisonResult comparisonResult;
        //Some code that uses sortAlgorithm.
        return comparisonResult;
    }
];

Это позволит отсортировать объекты по ключу name, чтобы любой ключ, начинающийся с @, например, @home, предшествует любой клавише, начинающейся с r, например radical, и это снова наступит раньше, чем любая клавиша, начинающаяся с a, например anything.

Выше приведен только пример. Смысл в том, чтобы включить полностью произвольную сортировку.

Это должно быть использовано для NSFetchedResultsController.

Как будет выглядеть код для // Какой-нибудь код, использующий алгоритм sortAlgorithm ?

EDIT:

Код, окружающий мою попытку реализовать sortDescriptor, как pr. occulus' предложение:

- (NSFetchedResultsController *)fetchedResultsController {
    if (__fetchedResultsController)
        return __fetchedResultsController;

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];

    fetchRequest.entity = [NSEntityDescription entityForName:@"Tag" inManagedObjectContext:self.temporaryManagedObjectContext];

    //NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:NO];
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:NO comparator:^(id obj1, id obj2) {

        NSArray *sortAlgorithm = [NSArray arrayWithObjects:@"#", @"!", @"@", @".", nil];

        NSString *obj1FirstChar = [(NSString *)obj1 substringToIndex:1];
        NSString *obj2FirstChar = [(NSString *)obj2 substringToIndex:1];
        int idx1 = [sortAlgorithm indexOfObject:obj1FirstChar];
        int idx2 = [sortAlgorithm indexOfObject:obj2FirstChar];

        if ( idx1 < idx2 )
            return NSOrderedAscending;
        else if ( idx1 > idx2 )
            return NSOrderedDescending;
        else
            return NSOrderedSame;
    }];

    fetchRequest.sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
    fetchRequest.fetchBatchSize = 20;        

    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.temporaryManagedObjectContext sectionNameKeyPath:nil cacheName:@"Tags"];

    aFetchedResultsController.delegate = self;
    self.fetchedResultsController = aFetchedResultsController;

    [self.fetchedResultsController performFetch:nil];

    return __fetchedResultsController;
}

Закомментированный sortDescriptor работает.

Определенно есть свойство с именем name в объектах сущности "Tag". Но даже если бы не было, это не проблема. Xcode, похоже, даже не компилирует эту строку кода (sortDescriptor), что звучит смешно. Точки останова работают просто отлично, но не ломаются в этой конкретной строке кода.

1 Ответ

3 голосов
/ 25 ноября 2011

Вам необходимо вытащить первые символы строк obj1 и obj2 как NSStrings, найти их индексы в массиве произвольного упорядочения, а затем сравнить позиции.

Примерно так: (поместите этот код в свой блок ^)

NSString *obj1FirstChar = [(NSString *)obj1 substringToIndex:1];
NSString *obj2FirstChar = [(NSString *)obj2 substringToIndex:1];
int idx1 = [sortAlgorithm indexOfObject:obj1FirstChar];
int idx2 = [sortAlgorithm indexOfObject:obj2FirstChar];

// NOTE: we haven't dealt with the case where one of the
// chars wasn't found in the array of characters. A strategy
// for this would need to be decided.

if (idx1 == idx2) {
    return NSOrderedSame;
}
if (idx1 < idx2) {
    return NSOrderedAscending;
}
return NSOrderedDescending;

Не проверено, может потребоваться небольшая настройка. Следите за различиями символов в верхнем / нижнем регистре.

ОБНОВЛЕНИЕ: Кажется, существуют проблемы с использованием пользовательских дескрипторов сортировки и хранилищ данных ядра с поддержкой SQL. Пожалуйста, см. этот вопрос для получения дополнительной информации.

...