如何对包含NSNull实例的NSMutableArray进行排序

时间:2010-12-23 17:29:55

标签: objective-c null nsmutablearray nssortdescriptor

我在我的组合框数据源数组中包含一个占位符[NSNull null],因此我可以允许用户选择“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。

当然,我可以将非null对象复制到一个单独的数组中,对其进行排序,重新插入null对象,并将其分配给数组属性 - 但这会使我的代码混乱。不应该有没有阻止NSNull的分类方法吗?毕竟,Apple明确提供了NSNull,允许我们将其包含在数组中。

2 个答案:

答案 0 :(得分:4)

主要问题是NSNull在已知元素之前或之后排序为什么? - 没有一般性答案 - 所以Apple不能用于通用方法。

在你的情况下,你是按sortUsingDescriptors排序 - 这从数组中的对象获取属性“name” - NSNull的属性“name”的值是多少?

因此,使用sortUsingDescriptors,您必须在描述时删除NSNull。

如果你想在数组中保留NSNull,你可以尝试使用另一种方式进行排序 - sortUsingFunction:context:将允许你编写一个可以处理NSNull的比较函数。 Apple Code只需要处理已知对象而不是它们包含的对象。

答案 1 :(得分:0)

这是我根据itaiferber的建议(并使用Apple的基础数据类型参考)得出的结果:

我把它放在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进行排序可以采用相同的方式进行,但我必须为每种实体类型提供不同的方法,以便提取字符串。

再次感谢Mark和itaiferber。