【问题标题】:how to sort an NSMutableArray that contains an instance of NSNull如何对包含 NSNull 实例的 NSMutableArray 进行排序
【发布时间】:2010-12-23 17:29:55
【问题描述】:

我在我的组合框数据源数组中包含了一个占位符 [NSNull null],这样我就可以允许用户选择“无”,而无需实际存储一个空白对象。问题是当一个真实的对象被添加到数据源数组中时,我需要对数组进行排序:

[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 以允许我们将其包含在数组中。

【问题讨论】:

    标签: objective-c null nsmutablearray nssortdescriptor


    【解决方案1】:

    主要问题是 NSNull 排序是什么 - 它是在已知元素之前还是之后? - 没有通用的答案 - 所以 Apple 不能提供通用方法。

    在您的情况下,您正在按 sortUsingDescriptors 排序 - 这从数组中的对象中获取属性“名称” - NSNull 的属性“名称”的值是什么?

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

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

    【讨论】:

    • 或者更好的是,您可以使用sortUsingComparator: 进行排序,它需要一个NSComparator 块,并且可以省去在代码中间添加一个不合适的函数的不便。
    • 感谢您的帮助!我从 Mark 的回答中看到,我对比较器很粗暴。至于解决方案,itaiferber 的建议看起来更简单,所以我先尝试了一下。我会将结果作为单独的答案发布。根据此链接,Mark 的建议将为方向性提供更多灵活性:thoughts.digital-transience.com/2009/03/sorting-nsarrays/…
    【解决方案2】:

    以下是我根据 itaiferber 的建议(并使用 Apple 的 Foundation Data Types Reference)得出的结论:

    我把这个放在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。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-11-08
      • 2010-10-22
      • 1970-01-01
      • 2015-08-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多