2013-08-01 61 views
2

我仍在学习目标C和iOS,并且遇到问题。我从CoreData创建一个包含纬度和经度的数组。我想把这个数组按照最近的位置排序。如何按距离排序数组iOS

这是我到目前为止有:

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; 
}]; 

有人能帮我把这两样东西一起工作吗?

+0

你在循环之前放了'sortUsingComparator'节吗? – Wain

+1

什么不起作用? –

回答

6

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

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

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

的代码看起来像这样(没有编译器检查!):

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的排序描述符添加到获取请求中,而不是先取回 ,然后再进行排序。当然,缺点是你必须在当前位置改变时重新计算 的所有值。

+0

感谢您的信息。我认为你的解决方案可以工作,但我正在遇到一个bug。运行时,它在project.currentDistance = @(米)处崩溃;与错误: - [TimeProjects setCurrentDistance:]:无法识别的选择器发送到实例。我加了@property(nonatomic,retain)NSNumber * currentDistance;到我的TimeProjects模型头文件。 – Keith

+0

@Keith:你不能只是将属性添加到头文件。您必须将currentDistance定义为Core Data模型中的瞬态属性。然后,您(重新)创建托管对象子类文件。 –

+0

谢谢马丁,我知道它的工作。我从来没有使用过瞬态属性,我必须更多地研究它们。 – Keith