NSComparator块未调用

时间:2013-08-14 09:47:12

标签: ios objective-c-blocks nssortdescriptor

我使用Core DataNSFetchRequest存储中提取数据并将数据存储在array中 - 一切正常。下一步,我想使用arrayNSSortDescriptors进行排序,如下所示:

array = [array sortedArrayUsingDescriptors:[NSArray arrayWithObjects:
            [NSSortDescriptor sortDescriptorWithKey:@"score" ascending:NO],
            [NSSortDescriptor sortDescriptorWithKey:@"score" ascending:NO comparator:^NSComparisonResult(id obj1, id obj2) {
                    if ([[[array objectAtIndex:[obj2 integerValue]] valueForKey:@"lessImportantItems"] containsObject:[array objectAtIndex:[obj1 integerValue]]]) {
                        return (NSComparisonResult)NSOrderedAscending;
                    } else {
                        return (NSComparisonResult)NSOrderedDescending;
                    }
                }],
            [NSSortDescriptor sortDescriptorWithKey:@"createdAt" ascending:NO], nil]];

我遇到的问题是第二个NSComparator中的NSSortDescriptor块未被调用(我尝试NSLog)。为了给我的数据结构提供一些背景知识,这里是相关的Core Data对象图部分:

http://screencast.com/t/AOY6IdNFWoK

应用程序的作用是将项目相互比较。作为第一步,配对比较中的获胜者获得score增量。但我也标记了一个成对的优先级,即我从赢家到输家添加了一对多的lessImportantItems关系。所以,在我的数组中,我首先尝试按score排序,然后,当score s相等时,我也尝试按配对优先级排序。

也许是因为我连续两次使用score作为比较器key?但是,另一方面,NSComparator不允许将relationship作为key传递。

我似乎无法解决这个问题。有人有什么想法吗?或许我应该采取不同的方法进行排序?

2 个答案:

答案 0 :(得分:1)

第二个排序描述符对我没有任何意义。它适用于给定的比较器 到要比较的对象的score属性。所以在比较器里面, obj1obj2是待比较对象的得分值。 您似乎尝试使用

获取基础对象
[array objectAtIndex:[obj1 integerValue]]
[array objectAtIndex:[obj2 integerValue]]

但这不起作用。所以第二个排序描述符应该看起来像

[NSSortDescriptor sortDescriptorWithKey:@"self" ascending:NO
        comparator:^NSComparisonResult(Item *item1, Item *item2) {

        // compare item1, item2 ...
}];

然后出现下一个问题:如何根据优先级比较两个对象? 您的代码主要执行以下操作:

if ([item2 valueForKey:@"lessImportantItems"] containsObject:item1]) {
    return NSOrderedAscending;
} else {
    return NSOrderedDescending;
}

但那不是一个合适的比较器:

  • 如果对象相等(不是“反身”),则不会返回NSOrderedSame
  • 对于两个“不相关的对象”,无论如何,它都将返回NSOrderedDescending 订单(不是“不对称”),
  • 它不会检测item1是否仅与item2间接相关(不是 “传递”)。

但是如何对“不相关的对象”进行排序?没有独特的解决方案。如果B和C都是 如果不如A重要,那么A,B,C和A,C,B都是有效的解决方案。 比较B和C时比较器应该返回什么?

所以我认为用排序描述符无法实现 你必须选择其他一些算法,例如"Topological sorting"

答案 1 :(得分:0)

如果有人有兴趣,这就是我如何实现我追求的排序。

我只使用上面示例中的第一个NSSortDescriptor来获取按array排序的score,然后我在array上调用了另一个排序方法:< / p>

array = [array sortedArrayUsingDescriptors:[NSArray arrayWithObjects:
            [NSSortDescriptor sortDescriptorWithKey:@"score" ascending:NO], nil];

array = [self applyMoreImportantPairOrdering:array];

这是方法:

+ (NSArray *)applyMoreImportantPairOrdering:(NSArray *)array {

    NSMutableArray *mutableArray = [NSMutableArray arrayWithArray:array];

    [array enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(id obj, NSUInteger idx, BOOL *stop) {

        if ([[obj valueForKey:@"score"] integerValue] > 0) {

            NSMutableSet *lessImportantItemsSet = [NSMutableSet setWithSet:[obj valueForKey:@"lessImportantItems"]];

            for (int i = idx - 1; i >= 0; i--) {

                NSManagedObject *objAbove = [array objectAtIndex:i];

                if ([[obj valueForKey:@"score"] integerValue] == [[objAbove valueForKey:@"score"] integerValue]) {

                    if ([lessImportantItemsSet containsObject:objAbove]) {

                        NSUInteger idxAbove = [mutableArray indexOfObject:objAbove];

                        [mutableArray removeObject:obj];
                        [mutableArray insertObject:obj atIndex:idxAbove];
                    }
                }
            }
        }
    }];

    return [NSArray arrayWithArray:mutableArray];
}

我需要lessImportantItemsSet的原因是因为当我在item中移动(删除并插入)array时,它会失去lessImportantItems关系。这样我就可以在完成特定item时维护不太重要的item列表/集。