2013-01-02 46 views
0

我在我的SQLite數據庫2500左右的記錄,每個記錄代表一個衆所周知的商店在我國的一個分支,我用distanceFromLocation比較當前用戶的位置和給定位置之間的距離像這樣:使用distanceFromLocation計算最近的5個地點effeciently

CLLocation* storeLocation = [[CLLocation alloc] initWithLatitude:lat longitude:lon]; 
double distance = [userLocation distanceFromLocation:storeLocation]; 

如何使用這段代碼(了一種有效的方式,不凍結UP THE UI)找到中存儲在本地數據庫對最近的5個分支?

編輯:

the code here是如何計算在數據庫級別上兩點之間的距離,一個很好的例子,所以這是非常有效的,但是但是,代碼是有點難以怎麼把它實現」訪問SQLite並手動創建查詢,任何人都可以爲我提供該代碼的工作示例,我將非常感激。

+0

你可以縮小每個地區/國家的搜索範圍嗎? – tiguero

+2

看看這個(高效)的答案和Kenny Winker的評論: http://stackoverflow.com/a/6828849/1611723 –

+0

這很難,DB中的每個商店記錄都與一個地區相關,該國家是分裂的進入主要地區,但無法知道當前用戶現在在哪個地區! – JAHelia

回答

3

但是你想這樣做,爲了避免阻塞UI,你必須在另一個線程中執行此操作。您可以通過多種方式實現此目的。下面是一個例子與GCD:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 

    NSArray *closestFive = [self closestFive]; 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     //Tell yourself something when the process finished 
     [self closestAre:closestFive]; 
    } 
}); 

[自closestFive]可以天真地通過的位置循環,計算距離,使用包裹在一個NSValue作爲密鑰CLLocation將它們存儲在字典中實現。對此進行排序,然後返回該數組的subarrayWithRange:。可能有更好的實現,但對於2500元,這是不是很多,這樣做就足夠了這種方式,只要你在後臺線程做

這可能是對它的一個實現:

- (NSArray *)closestFive:(CLLocation *)location from:(NSArray *)locations 
{ 
    NSMutableArray *distances = [NSMutableArray arrayWithCapacity:locations.count]; 

    for (CLLocation *l in locations) { 
     NSDictionary *d = @{ 
      @"location" : l, 
      @"distance" : @([location distanceFromLocation:l]) 
     }; 
     [distances addObject:d]; 
    } 
    [distances sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) { 
     double d1 = [obj1[@"distance"] doubleValue]; 
     double d2 = [obj1[@"distance"] doubleValue]; 

     if (d1 > d2) { 
      return NSOrderedDescending; 
     } 
     else if (d1 < d2) { 
      return NSOrderedAscending; 
     } 
     return NSOrderedSame; 
    }]; 
    return [[distances subarrayWithRange:NSMakeRange(0, 5)] valueForKey:@"location"]; 
}