为什么这个NSPredicate不起作用?

avf*_*avf 1 comparison performance cocoa predicate nspredicate

我有一个MKAnnotation名为的对象数组arrAnnotations.我想从与CLLocation名为"newLocation" 的对象中存储的坐标相同的坐标中选择一个注释.

我正在尝试使用a NSPredicate,但它不起作用.

NSPredicate *predicate = [NSPredicate  predicateWithFormat:@"(SELF.coordinate == %f)", newLocation.coordinate];
NSArray* filteredArray = [arrAnnotations filteredArrayUsingPredicate:predicate];
[self.mapView selectAnnotation:[filteredArray objectAtIndex:0] animated:YES];
Run Code Online (Sandbox Code Playgroud)

filteredArray始终包含零个对象.

我也试过以下,但也无效

NSPredicate *predicate = [NSPredicate  predicateWithFormat:@"(coordinate == %f)", newLocation.coordinate];
Run Code Online (Sandbox Code Playgroud)

NSPredicate *predicate = [NSPredicate  predicateWithFormat:@"(coordinate > 0)"];
Run Code Online (Sandbox Code Playgroud)

NSPredicate *predicate = [NSPredicate  predicateWithFormat:@"(coordinate.latitude == %f)", newLocation.coordinate.latitude];
Run Code Online (Sandbox Code Playgroud)

最后两个崩溃了应用程序,第三个崩溃了NSInvalidArgumentExceptionfor [NSConcreteValue compare:]和第四个,因为latitude它不符合键值编码(我认为这是因为坐标只是一个c-struct而不是一个NSObject?).

我该如何使用它NSPredicate?任何人都可以给我一个链接到一个文件,显示Predicates如何在幕后工作?我不明白他们实际做了什么,尽管我已阅读并理解Apple的Predicate Programming Guide的大部分内容.正在使用for ... in构造中搜索带有谓词的大型数组比使用谓词循环更有效吗?如果是/否,为什么?

Fel*_*ino 6

MKAnnotation协议的坐标属性是CLLocationCoordinate2D struct,因此NSPredicate根据谓词格式字符串语法不允许格式语法

你可以用它NSPredicate predicateWithBlock:来完成你想要做的事情,但你要小心CLLocationCoordinate2D并且如何比较它是否相等.

CLLocationCoordinate2Dlatitudelongitude特性是CLLocationDegrees数据类型,这是一个double由定义.

通过快速搜索,您可以找到在比较浮点值是否相等时将遇到的几个问题示例.一些很好的例子可以找到这里,这里这里.

鉴于所有这些,我相信使用代码bellow为您的谓词可能会解决您的问题.

NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {

    id<MKAnnotation> annotation = evaluatedObject;

    if (fabsf([annotation coordinate].latitude - [newLocation coordinate].latitude) < 0.000001 
            && fabsf([annotation coordinate].longitude - [newLocation coordinate].longitude) < 0.000001) {
        return YES;
    } else {
        return NO;
    }

}];
Run Code Online (Sandbox Code Playgroud)