Как отсортировать NSMutableArray, который содержит экземпляр NSNull
Я включил заполнитель [NSNull null] в мой массив источника данных combobox, чтобы я мог позволить пользователю выбрать "none" без фактического сохранения пустого объекта. Проблема в том, что когда в массив источника данных добавляется реальный объект, мне нужно отсортировать массив:
[self.mutableArrayOfStrings sortUsingSelector:@selector(caseInsensitiveCompare:)];
Эта линия производит SIGKILL.
У меня та же проблема с сопутствующим массивом NSManagedObject, который также имеет заполнитель NSNull:
NSSortDescriptor *sortDescriptorName = [[NSSortDescriptor alloc] initWithKey:@“name” ascending:YES selector:@selector(caseInsensitiveCompare:)];
NSArray *sortDescriptorsNames = [[NSArray alloc] initWithObjects: sortDescriptorName, nil];
[self.mutableArrayOfMOs sortUsingDescriptors:sortDescriptorsNames];
Если mutableArrayOfMOs содержит объект NSNull, эта строка также создает SIGKILL.
Конечно, я мог бы скопировать ненулевые объекты в отдельный массив, отсортировать его, повторно вставить нулевой объект и назначить его свойству массива - но это загромождает мой код. Разве не должно быть способов сортировки, которые не давят NSNull? В конце концов, Apple предоставила NSNull явно, чтобы позволить нам включать его в массивы.
2 ответа
Основная проблема в том, что NSNull сортирует как-до или после известного элемента? - нет общего ответа - поэтому Apple не может использовать метод общего назначения.
В вашем случае вы сортируете по sortUsingDescriptors - это берет свойство "name" из объектов в массиве - каково значение свойства "name" для NSNull?
Таким образом, используя sortUsingDescriptors, вы должны удалить NSNull, как вы описываете.
Если вы хотите сохранить NSNull в массиве, вы можете попробовать сортировку другим способом - sortUsingFunction:context: позволит вам написать функцию сравнения, которая может работать с NSNull. Код Apple имеет дело только с известными объектами, а не с тем, что они содержат.
Вот то, что я придумал в результате предложения itaiferber (и используя справочник типов данных Apple Foundation):
Я положил это в файл h:
typedef NSComparisonResult (^NSComparator)(id string1, id string2);
Я добавил этот метод:
- (NSArray *) sortNullsToTopInStringArray:(NSArray *)array {
NSArray *sortedArray = [array sortedArrayUsingComparator: ^(id string1, id string2) {
// First test for null object. It should go to top (beginning) of list.
if ([string1 class] == [NSNull class])
return (NSComparisonResult)NSOrderedAscending;
if ([string2 class] == [NSNull class])
return (NSComparisonResult)NSOrderedDescending;
// For non-null strings, use regular NSString compare method, and wrap it in NSComparisonResult.
switch ([string1 caseInsensitiveCompare:string2]) {
case NSOrderedAscending:
return (NSComparisonResult)NSOrderedAscending;
case NSOrderedSame:
return (NSComparisonResult)NSOrderedSame;
case NSOrderedDescending:
return (NSComparisonResult)NSOrderedDescending;
default:
return (NSComparisonResult)NSOrderedAscending;
}
}];
return sortedArray;
}
и использовал это здесь:
NSArray *sortedArray = [self sortNullsToTopInStringArray:self.mutableArrayOfStrings];
NSMutableArray *sortedMutableArray = [sortedArray mutableCopy];
self.mutableArrayOfStrings = sortedMutableArray;
[sortedMutableArray release];
Сортировка NSManagedObjects может быть сделана таким же образом, но я должен был бы предоставить различные методы для каждого типа сущности, чтобы извлечь строки.
Еще раз спасибо Марку и Итайферберу.