【问题标题】:NSSortDescriptor - sort by locationNSSortDescriptor - 按位置排序
【发布时间】:2012-08-15 04:47:10
【问题描述】:

我在 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 从不打印。

我在这里错过了什么?

【问题讨论】:

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


    【解决方案1】:

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

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

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

    【讨论】:

    • 这不是违背了在数据库中进行高效排序的目的吗?如果我得到结果(大约 15,000 个),将它们存储在一个数组中,然后对它们进行排序,那会不会非常低效?
    • 文档说,获取请求的排序描述符应该使用存储在数据库中的属性。原因是(我假设)排序是在 SQLite 层中完成的。
    • @MartinR SQLite等关系型数据库有自己的内置排序机制;我不相信有办法通过提供比较器块来动态自定义它。
    • @jlehr:是的,我就是这么想的。
    • @MartinR 哎呀,我不小心引用了错误的用户 ID——我之前的评论实际上是为了回答 Aaron 的问题。
    【解决方案2】:

    对此的另一种看法是在您的“停止” managedObject 上拥有一个名为 meanSquared 的属性(可能是 NSDecimalNumber)。

    当您的设备纬度/经度移动到足以改变“最近停止”数据时,您将使用均方距离更新所有“停止”对象(即 (yourLat-stopLat)^2+(yourLong-stopLong)^2 ),然后只需在您的 sortDescriptor 中使用 'meanSquared'。

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

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

        我会推荐以下方法:

        请参阅“地理位置谓词”部分 http://www.objc.io/issue-4/core-data-fetch-requests.html

        它使用谓词获得近似结果,然后在内存中准确排序。

        【讨论】:

        • 谢谢,这是一个有用的方法。
        • 由于 MapKit 方法,其中一些是多余的
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-10-06
        • 1970-01-01
        • 2014-12-29
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多