Изменен порядок объектов в массиве без вызова для него - PullRequest
0 голосов
/ 20 июля 2011

Я работаю над приложением, использующим MapKit в iOS.У меня возникли проблемы, потому что в какой-то момент во время моей программы переключается порядок одного из массивов (массив, содержащий координаты), в результате чего названия мест соединяются с неправильными координатами.Я сузил его до следующей области:

for(CLLocation *loc in locationOutputArray)
{
    NSLog(@"Location coordinates: %f,%f",[loc coordinate].latitude,
                                         [loc coordinate].longitude);
}
NSLog(@"***************************************");
for(CLLocation *location in locationOutputArray)
{
    CLGeocoder *geocoder = [[CLGeocoder alloc] init];
    [geocoder reverseGeocodeLocation:location
                   completionHandler:^(NSArray *placemarks, NSError *error)
     {

         NSLog(@"Location coordinates:%f,%f",[location coordinate].latitude,
                                             [location coordinate].longitude);
         if(placemarks && placemarks.count > 0)
         {
             CLPlacemark *topResult = [placemarks objectAtIndex:0];

             //NSLog(@"%@",topResult);

             NSString *address = [NSString stringWithFormat:@"%@ %@, %@ %@",
                                  [topResult subThoroughfare],
                                  [topResult thoroughfare],
                                  [topResult locality],
                                  [topResult administrativeArea]];
             //NSLog(@"Address: %@", address);

             [addressOutputArray addObject:address];


             Place *place = [[Place alloc]
                             initWithName:[namesOutputArray objectAtIndex:([addressOutputArray count]-1)]
                               andAddress:address
                              andLatitude:[location coordinate].latitude 
                             andLongitude:[location coordinate].longitude
                    andStartingCoordinate:startingCoordinate];

             //NSLog(@"Distance from starting location: %f",[place distanceFromStartingPoint]);

             [finalPlaceArray addObject:place];
             [place release];
}`

Операторы журнала для до и после блока кода соответственно (разделенные звездочками):

Координаты местоположения:40.116903, -75.120631
Координаты местоположения: 40.129940, -75.060127
Координаты местоположения: 40.083996, -75.187704
Координаты местоположения: 40.069180, -75.126812
Координаты местоположения: 40.095425, -75.127777
Координаты местоположения:40.095019, -75.126752
Координаты местоположения: 40.117596, -75.185366
Координаты местоположения: 40.105838, -75.212272
Координаты местоположения: 40.124327, -75.061865
Координаты местоположения: 40.010910, -75.127223
Координаты местоположения:40.061088, -75.092801
Координаты местоположения: 40.112011, -75.165353
Координаты местоположения: 40.017103, -75.174498
Координаты местоположения: 40.139532, -75.207757
Координаты местоположения: 40.099432, -75.196213


Координаты местоположения: 40.116903, -75.120631
Locaкоординаты местоположения: 40.061088, -75.092801
Координаты местоположения: 40.010910, -75.127223
Координаты местоположения: 40.124327, -75.061865
Координаты местоположения: 40.112011, -75.165353
Координаты местоположения: 40.099432, -75.196213
Координаты местоположения: 40.139532, -75.207757
Координаты местоположения: 40.017103, -75.174498
Координаты местоположения: 40.083996, -75.187704
Координаты местоположения: 40.069180, -75.126812
Координаты местоположения: 40.129940, -75.060127
Координаты местоположения: 40.095019, -75.126752
Координаты местоположения: 40.117596, -75.185366
Координаты местоположения: 40.095425, -75.127777
Координаты местоположения: 40.105838, -75.212272

Любая помощь будетвысоко ценится.

Ответы [ 2 ]

3 голосов
/ 21 июля 2011

Краткий ответ: Вы печатаете местоположения в порядке, в котором геокодер запрашивает выполнение, а не в порядке их появления в массиве.

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

Решение: Не полагайтесь на асинхронные вызовы для завершения в каком-либо конкретном порядке.Если вам нужно, чтобы результаты отображались в определенном порядке, вам потребуется способ их сортировки.Похоже, вы храните названия мест и местоположения в отдельных массивах и пытаетесь сохранить порядок этих массивов одинаковым.Это всегда рецепт для ошибок;Вам лучше хранить все в одном массиве, где каждая запись в массиве содержит как название места, так и местоположение.Использование словаря для каждого места может быть удобным способом достижения этого.

2 голосов
/ 21 июля 2011

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

for(CLLocation *location in locationOutputArray)
{
    NSLog(@"Location coordinates:%f,%f",[location coordinate].latitude,
                                        [location coordinate].longitude);
    CLGeocoder *geocoder = [[CLGeocoder alloc] init];
    [geocoder reverseGeocodeLocation:location
                   completionHandler:^(NSArray *placemarks, NSError *error)
     {
...

Теперь, когда ваш finalPlaceArray вышел из строя, вам нужно будет реализовать что-то вроде очистки finalPlaceArray перед первым циклом for, где вы печаталиожидаемые результаты и затем добавьте [NSNull null] к каждому индексу в цикле.В вашем обработчике завершения вы можете заменить объект с правильным индексом.

[finalPlaceArray replaceObjectAtIndex:[locationOutputArray indexOfObject:location] withObject:place];
...