2013-11-07 2 views
2

Мне нужно геокодировать тонну адресов с помощью CLGeocoder, не API Google.Геокодирование много адресов - CLGeocoder

Моя проблема заключается в том, что мой код добавляет только аннотацию для первого адреса в массиве ниже. Тем не менее, функция вызывается соответствующее число раз - блок просто запускается в первый адрес после того, как функция была вызвана для всех адресов:

- (void)mapPoints { 
    NSString *foo = [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"names%d", self.indexOfSchool] ofType:@"plist"]; 
    NSArray *description = [NSArray arrayWithContentsOfFile:foo]; 
    NSString *bar = [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"%d1", self.indexOfSchool] ofType:@"plist"]; 
    NSArray *details = [NSArray arrayWithContentsOfFile:bar]; 

    NSString *path = [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"%d0", self.indexOfSchool] ofType:@"plist"]; 
    NSArray *addresses = [NSArray arrayWithContentsOfFile:path]; 
    self.saved = [NSMutableArray alloc] init]; 
    for (int q = 0; q < addresses.count; q+= 20) { 
     [self annotate:[addresses objectAtIndex:q] detail:[details objectAtIndex:q] andDesc:[description objectAtIndex:q]]; 
    } 
} 

see updated annotate: method below... 

Вот как выглядят мои журналы:

Поэтому, хотя функция вызывается с помощью цикла, блок не работает для каких-либо результатов, отличных от первого.

Я знаю, что мои адреса хороши. Это не работает для любого числа (> 1) вызовов функции. += 20 в цикле не имеет ничего общего с построением только одной точки: это тоже не работает для ++ (также есть около 200 результатов).

Я довольно новичок в блоках, поэтому, надеюсь, это простое решение. Любая помощь очень ценится!

EDIT Делать это вместо:

- (void)annotate:(NSString *)address detail:(NSString *)detail andDesc:(NSString *)description { 
    CLGeocoder *geocoder = [[CLGeocoder alloc] init]; 
    [geocoder geocodeAddressString:address 
      completionHandler:^(NSArray* placemarks, NSError* error) { 
       if (placemarks && placemarks.count > 0) { 
        CLPlacemark *topResult = [placemarks objectAtIndex:0]; 
        MKPlacemark *placemark = [[MKPlacemark alloc] initWithPlacemark:topResult]; 
        MKPointAnnotation *point = [[MKPointAnnotation alloc] init]; 
        point.coordinate = placemark.coordinate; 
        point.title = description; 
        point.subtitle = [NSString stringWithFormat:@"%@ miles from origin", detail]; 
        MKCoordinateRegion region = self.directionsView.region; 
        region.center = [(CLCircularRegion *)placemark.region center]; 
        region.span.longitudeDelta /= 8.0; 
        region.span.latitudeDelta /= 8.0; 
        [self.directionsView addAnnotation:point]; 
        NSLog(@"%@", point); 
        [self.directionsView setRegion:region animated:YES]; 
       } 
      } 
]; 
    [self.saved addObject:geocoder]; 
    NSLog(@"%@", geocoder); 
} 

... до сих пор тянет пустую карту без каких-либо аннотаций - даже не первый. Массив геокодера имеет различный адрес памяти при каждом вызове функции, так что часть, кажется, работает.

+0

Я думаю, вы должны пойти с семафоров в ГКД. – Shmidt

ответ

5

Вы вызываете geocodeAddressString несколько раз подряд, но документы от Apple говорят

После инициирования запроса вперед геокодирования, не пытайтесь инициировать другой Форвард или обратного геокодирования запрос.

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

+1

Не повезло. См. Мое редактирование. – eulr

+0

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

+0

Я использую ARC - не сохраняя – eulr

3

Каждый объект CLGeocoder может обрабатывать только один запрос за раз. Попробуйте создать новый объект CLGeocoder внутри вашего метода annotate вместо повторного использования одного объекта, сохраненного в свойстве. Пока у вас включен ARC, вы должны быть в порядке.

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

+0

Не повезло. См. Мое редактирование. – eulr

+0

@ 9fermat Не могли бы вы опубликовать весь обновленный метод 'annotate'? Вы увидите это поведение, если вы все еще пытаетесь использовать 'self.geocoder' вместо' geocoder'. Кроме того, что вы подразумеваете под «экземпляром вместо свойства»? – godel9

+0

Я имею в виду, что я не использую 'self.geocoder', а просто' geocoder' - экземпляр, а не свойство. – eulr

1

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

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

+0

Как бы вы начали новый запрос в предыдущем? – eulr

+0

@ 9fermat Я имел массив адресов как свойство и начал все это, вызвав '[self geocodeAddressAtIndex: 0];'. Затем в блоке завершения геокодирования я просто вызываю рекурсивно тот же метод с инкрементированным индексом: '[self geocodeAddressAtIndex: (i + 1)];' – Tricertops

-1

Это Xamarin псевдо-код, но он должен работать так же, в родной, как я должен был преобразовать в C# в первую очередь:

forloop() 
{ 
    var geocoder = new CLGeocoder(); 
    var placemarks = await geocoder.GeocodeAddressAsync(address); 
} 
Смежные вопросы