Сортировка NSManagedObjects от ближайшего к дальнему от текущего местоположения

У меня есть модель Core Data, определенная с двумя атрибутами

  • (Двойная) широта
  • (Двойная) долгота

Теперь я хотел бы получить эти объекты и отсортировать их в зависимости от того, насколько далеко они отстоят от текущего местоположения пользователя. Я уже знаю, как получить текущее местоположение, но до сих пор не могу понять, как сортировать результаты в зависимости от двух атрибутов.

Я искал что-то подобное, но я все еще немного смущен.

Было бы здорово, если бы кто-нибудь мог указать мне правильное направление.

Спасибо


person Titouan de Bailleul    schedule 27.05.2012    source источник


Ответы (3)


Сортировка с блоком компаратора довольно проста

NSArray *positions = //all fetched positions
CLLocation *currentLocation   = // You said that you know how to get this.


positions = [positions sortedArrayUsingComparator: ^(id a, id b) {
    CLLocation *locationA    = [CLLocation initWithLatitude:a.latitude longitude:a.longitude];
    CLLocation *locationB    = [CLLocation initWithLatitude:b.latitude longitude:b.longitude];
    CLLocationDistance dist_a= [locationA distanceFromLocation: currentLocation];
    CLLocationDistance dist_b= [locationB distanceFromLocation: currentLocation];
    if ( dist_a < dist_b ) {
        return (NSComparisonResult)NSOrderedAscending;
    } else if ( dist_a > dist_b) {
        return (NSComparisonResult)NSOrderedDescending;
    } else {
        return (NSComparisonResult)NSOrderedSame;
    }
}

Как я только что узнал от Инафцигера, вы должны добавить к этому полезный хак/обходной путь¹, который он показывает.


¹выберите из этих слов тот, который имеет для вас наиболее позитивный оттенок

person vikingosegundo    schedule 27.05.2012
comment
+1 отличный способ сделать это! Пожалуйста, посмотрите мой ответ об ошибке в DistanceFromLocation и обходном пути, чтобы получить правильное значение. - person lnafziger; 28.05.2012
comment
Я видел, но не хотел воровать :) - person vikingosegundo; 28.05.2012
comment
Украсть. Я предпочитаю обходной путь, а не взлом, лол. :) - person lnafziger; 28.05.2012
comment
для меня взлом — это небольшое, но элегантное решение, а обходной путь — это то, что я делаю и ненавижу, поскольку маркетологи установили крайний срок, и я собираюсь его взломать. - person vikingosegundo; 28.05.2012
comment
Ха-ха, и я полагаю, что работаю над ошибкой, которая есть у Apple... Не беспокойтесь, я просто шучу больше всего на свете! - person lnafziger; 28.05.2012
comment
@lnafziger, см. мое редактирование для решения о взломе/обходном пути. - person vikingosegundo; 28.05.2012
comment
Хорошо, я попробовал это один раз с 3 контактами, и это работает. Можно сказать, что достаточно :). Спасибо за отличный ответ. - person Titouan de Bailleul; 28.05.2012

Вероятно, вы захотите преобразовать пары долгота/широта в географическое расстояние между точками, а затем отсортировать по этому единственному атрибуту.

Вот статья о некоторых методах преобразования, в зависимости от того, какие приближения вы хотите принять: http://en.wikipedia.org/wiki/Geographical_distance

person Phillip Mills    schedule 27.05.2012

Ну, ты не можешь.

Во всяком случае, не только путем сортировки по широте/долготе. :)

Вам понадобится свойство, которое содержит расстояние от вашего текущего местоположения. Вы можете сделать это, добавив переходное свойство, которое рассчитывается по мере необходимости, или создав другой массив с расстояниями (вероятно, проще).

Чтобы рассчитать расстояние от вашего текущего местоположения, используйте этот метод:

CLLocation *currentLocation   = // You said that you know how to get this.
CLLocation *storedLocation    = [CLLocation initWithLatitude:object.latitude 
                                                   longitude:object.longitude];
/*
 * Calculate distance in meters
 * Note that there is a bug in distanceFromLocation and it gives different
 * values depending on whether you are going TO or FROM a location. 
 * The correct distance is the average of the two:
 */
CLLocationDistance *distance1 = [currentLocation distanceFromLocation:storedLocation];
CLLocationDistance *distance2 = [storedLocation distanceFromLocation:currentLocation];
CLLocationDistance *distance  = distance1 / 2 + distance2 / 2;
person lnafziger    schedule 27.05.2012
comment
Я заинтригован тем, почему вам нужно вычислить двойное расстояние между двумя точками, а затем сделать расстояние1/2 + расстояние2/2. Не могли бы вы сказать мне, почему? - person Titouan de Bailleul; 27.05.2012
comment
Попробуйте: рассчитайте расстояние от местоположения 1 до местоположения 2 и сравните его с расстоянием от местоположения 2 до местоположения 1. Они разные. (Это известная ошибка в DistanceFromLocation.) Как ни странно, среднее значение является правильным. - person lnafziger; 28.05.2012
comment
Я бы определенно объединил свой ответ с @TDeBailleul, чтобы получить лучшее решение для этого! - person lnafziger; 28.05.2012