如何通过iOS与距离对数组进行排序

时间:2013-08-01 19:50:43

标签: ios objective-c

我还在学习目标C和iOS,但我遇到了一个问题。我正在从CoreData创建一个包含纬度和经度的数组。我想拿这个数组并按最近的位置排序。

这是我到目前为止所做的:

NSError *error = nil;
NSFetchRequest *getProjects = [[NSFetchRequest alloc] init];
NSEntityDescription *projectsEntity = [NSEntityDescription entityForName:@"TimeProjects" inManagedObjectContext:context];

[getProjects setEntity:projectsEntity];
projectArray = [[context executeFetchRequest:getProjects error:&error] mutableCopy];

for (NSObject *project in projectArray) {
    // Get location of house
    NSNumber *lat = [project valueForKey:@"houseLat"];
    NSNumber *lng = [project valueForKey:@"HouseLng"];


    CLLocationCoordinate2D coord;
    coord.latitude = (CLLocationDegrees)[lat doubleValue];
    coord.longitude = (CLLocationDegrees)[lng doubleValue];

    houseLocation = [[CLLocation alloc] initWithLatitude:coord.latitude longitude:coord.longitude];
    //NSLog(@"House location: %@", houseLocation);

    CLLocationDistance meters = [houseLocation distanceFromLocation:currentLocation];

}

我也有这个排序代码,但我不知道如何将两者放在一起。

[projectArray sortUsingComparator:^NSComparisonResult(id o1, id o2) {
    CLLocation *l1 = o1, *l2 = o2;

    CLLocationDistance d1 = [l1 distanceFromLocation:currentLocation];
    CLLocationDistance d2 = [l2 distanceFromLocation:currentLocation];
    return d1 < d2 ? NSOrderedAscending : d1 > d2 ? NSOrderedDescending : NSOrderedSame;
}];

有人可以帮我解决这两件事吗?

1 个答案:

答案 0 :(得分:6)

您的sortUsingComparator数据块需要CLLocation个对象,而不是您的实例 核心数据类。这很容易解决,但我建议的是:

  • transient 属性currentDistance添加到您的实体。 (瞬态属性不存储在持久性存储文件中。)类型应为“Double”。
  • 获取对象后,为currentDistance中的所有对象计算projectArray
  • 最后使用projectArray键上的排序描述符对currentDistance数组进行排序。

优点是到目前位置的距离仅针对每个对象计算一次,而不是在比较器方法中重复计算。

代码看起来像这样(不是编译器检查!):

NSMutableArray *projectArray = ... // your mutable copy of the fetched objects
for (TimeProjects *project in projectArray) {
    CLLocationDegrees lat = [project.houseLat doubleValue];
    CLLocationDegrees lng = [project.houseLng doubleValue];
    CLLocation *houseLocation = [[CLLocation alloc] initWithLatitude:lat longitude:lng];
    CLLocationDistance meters = [houseLocation distanceFromLocation:currentLocation];
    project.currentDistance = @(meters);
}
NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"currentDistance" ascending:YES]
[projectArray sortUsingDescriptors:@[sort]];

或者,您可以使currentDistance成为实体的持久性属性,并在创建或修改对象时对其进行计算。优点是你可以添加 基于currentDistance的获取请求而不是获取的排序描述符 首先,然后排序。缺点当然是你必须重新计算 当前位置发生变化时的所有值。