2013-08-01 77 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