启用 ARC 后,NSComparator 在排序 NSArray 时改变行为

Posted

技术标签:

【中文标题】启用 ARC 后,NSComparator 在排序 NSArray 时改变行为【英文标题】:NSComparator changes behaviour while sorting NSArray when ARC is enabled 【发布时间】:2014-01-30 15:18:55 【问题描述】:

我正在使用 NSComparator 对 NSArray 中的对象进行排序。当代码未启用 ARC 时,比较器会给出与启用 ARC 时不同的结果。

以下是我的代码 sn-p:

- (NSArray *)sortedToolsInfoArrayWithKey 
    NSArray *aReturnVal = nil;
    NSArray *aToolsInfoArray = [[NSArray alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"ToolsData" ofType:@"plist"]];

aReturnVal = [aToolsInfoArray sortedArrayUsingComparator:(NSComparator)^(NSDictionary *a, NSDictionary *b) 
    [[a valueForKey:@"selectionCount"] compare:[b valueForKey:@"selectionCount"]];
];

[aToolsInfoArray release];
return aReturnVal;

同样的方法是用非 ARC 代码编写的,我需要相同类型的排序数组,请注意,我的要求是我需要对从两个不同文件中的同一个 pList 文件中挑选的同一个数组进行排序,其中一个文件启用 ARC 而其他文件未启用 ARC。 但是当我这样做时,我得到了完全相反的排序顺序,当我禁用 ARC 时,问题就解决了。

我无法理解 NSComparator 对 ARC 和未启用 ARC 的文件中的数组进行排序的不同行为背后的逻辑。

谢谢..

【问题讨论】:

用您的 plist 文件中的一些条目更新您的问题,以便我们看到您正在处理的内容。 【参考方案1】:

您没有 return 比较器块中的值:

aReturnVal = [aToolsInfoArray sortedArrayUsingComparator:^(id a, id b) 
    NSDictionary *adict = (NSDictionary *)a;
    NSDictionary *bdict = (NSDictionary *)b;
    return [[adict objectForKey:@"selectionCount"] compare:[bdict objectForKey:@"selectionCount"]];
];

(加上使用objectForKey 而不是valueForKey,这是KVC 访问器)。

编辑错过了您使用的块语法也不正确(感谢@Ivan Genchev)。

【讨论】:

return 很好。但是缺少return 不会导致编译器错误吗? @rmaddy 是的,我希望它会。我假设 OP 已经发布了他的实际代码,不过...... 刚刚尝试过,它不会导致错误,甚至不会导致警告,因为他正在将该块投射到NSComparator @rmaddy 请特别参阅NSObjCRuntime.htypedef NSComparisonResult (^NSComparator)(id obj1, id obj2); @IvanGenchev 不错。错过了。【参考方案2】:

作为“***foe”答案的后续,您的块语法错误。你需要:

aReturnVal = [aToolsInfoArray sortedArrayUsingComparator:^NSComparisonResult(NSDictionary *a, NSDictionary *b) 
    return [[a valueForKey:@"selectionCount"] compare:[b valueForKey:@"selectionCount"]];
];

让 Xcode 的代码完成功能为您填写所有内容。它避免了你所犯的那种错误。

【讨论】:

【参考方案3】:

您还可以使用NSSortDescriptor 对数组进行排序。

NSArray *testArray = @[@@"selectionCount":@"3",
            @@"selectionCount":@"1",
            @@"selectionCount":@"7",
            @@"selectionCount":@"2"];
NSLog(@"testArray: %@", testArray);
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"selectionCount" ascending:YES];
NSArray *sortedTestArray = [testArray sortedArrayUsingDescriptors:@[sortDescriptor]];
NSLog(@"sortedTestArray: %@", sortedTestArray);

【讨论】:

以上是关于启用 ARC 后,NSComparator 在排序 NSArray 时改变行为的主要内容,如果未能解决你的问题,请参考以下文章

objective-c启用ARC时的内存管理 (循环引用)

如何在 xcode 中将启用 ARC 的 .a 文件添加到非 ARC 项目

如何以编程方式为非 ARC xcode 项目中的特定文件启用 ARC?

为啥在启用 ARC 的项目中不需要维护保留计数

生成启用 ARC 的 UUID 字符串

在启用 ARC 的代码中修复警告“在此块中强烈捕获 [an object] 可能会导致保留周期”