NSSortDescriptor - 按位置排序

时间:2012-08-19 15:43:38

标签: objective-c ios cocoa-touch core-data core-location

我在Core Data中有一个地理位置列表(实体名称是“Stops”)。

我想按当前位置对它们进行排序,这样我就可以向用户显示哪些位置在附近。我正在使用NSFetchedResultsController,以便可以在UITableView中轻松显示结果。

我使用以下代码尝试此类:

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"stop_lat" ascending:YES comparator:^NSComparisonResult(Stops *obj1, Stops *obj2) {
    CLLocation *currentLocation = locationManager.location;

    CLLocation *obj1Location = [[CLLocation alloc]initWithLatitude:[obj1.stop_lat doubleValue] longitude:[obj1.stop_lon doubleValue]];
    CLLocation *obj2Location = [[CLLocation alloc]initWithLatitude:[obj2.stop_lat doubleValue] longitude:[obj2.stop_lon doubleValue]];

    CLLocationDistance obj1Distance = [obj1Location distanceFromLocation:currentLocation];
    CLLocationDistance obj2Distance = [obj2Location distanceFromLocation:currentLocation];

    NSLog(@"Comparing %@ to %@.\n  Obj1 Distance: %f\n  Obj2 Distance: %f",obj1.stop_name, obj2.stop_name, obj1Distance, obj2Distance);

    if (obj1Distance > obj2Distance) {
        return (NSComparisonResult)NSOrderedDescending;
    }

    if (obj1Distance < obj2Distance) {
        return (NSComparisonResult)NSOrderedAscending;
    }

    return (NSComparisonResult)NSOrderedSame;
}];

NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
[fetchRequest setEntity:[NSEntityDescription entityForName:[Stops entityName] inManagedObjectContext:context]];

frcNearby = [[NSFetchedResultsController alloc]
          initWithFetchRequest:fetchRequest
          managedObjectContext:context
          sectionNameKeyPath:nil
          cacheName:nil];

NSError *error;
BOOL success = [frcNearby performFetch:&error];
if (error) NSLog(@"ERROR: %@ %@", error, [error userInfo]);

但是,我的NSFetchedResultsController只是返回按我指定的键(“stop_lat”)排序的所有项目,而不是按用户的当前位置排序。

看起来我的比较器块没有被调用,因为那里的NSLog从不打印。

我在这里缺少什么?

4 个答案:

答案 0 :(得分:6)

基于Objective-C的排序描述符不能与获取请求一起使用。

来自“核心数据编程指南”:

  

...总而言之,如果直接执行提取,   您通常不应添加基于Objective-C的谓词或排序   获取请求的描述符。相反,你应该应用这些   获取的结果。

答案 1 :(得分:3)

对此的另一种看法是在'Stop'被管对象上有一个名为meanSquared的属性(可能是NSDecimalNumber)。

当你的设备lat / long移动到足以改变'最近的Stop'数据时,你用meanSquared距离更新所有'Stop'对象(即(yourLat-stopLat)^ 2 +(yourLong-stopLong)^ 2 ),然后在sortDescriptor中使用'meanSquared'。

根据您更新用户位置的次数,停靠点之间的距离和停靠次数,这可能是最佳解决方案。

答案 2 :(得分:1)

无论如何,您无法按纬度/经度排序,您需要计算每个点的距离并按此排序。或者在用户附近获取一系列lat / Lon值,获取该子集,计算它们的距离并显示。范围就像用户的纬度+/- 0.1度等,用于获取。

答案 3 :(得分:1)

我建议采用以下方法:

查看“地理位置谓词”&#39;部分 http://www.objc.io/issue-4/core-data-fetch-requests.html

使用谓词得到近似结果,然后在内存中准确地对它们进行排序。