В iPhone как узнать, когда все аннотации моей карты были загружены при использовании прямого геокода?

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

Проблема заключалась в том, что когда я запускал метод масштабирования непосредственно после того, как метод addAnnotations в представлении появился, он запустил процесс масштабирования до того, как мои аннотации смогли получить правильные координаты. Это приводит к неправильному увеличению масштаба, и мои аннотации перемещаются в правильное местоположение.

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

Вот мое мнение действительно появилось:

[super viewDidAppear:animated];

[businessMap removeAnnotations:businessPoints];
[businessPoints removeAllObjects];

UINavigationController *navVC = (UINavigationController *) [self.tabBarController.viewControllers objectAtIndex:0];

FirstViewController *VC = [navVC.viewControllers objectAtIndex:0];

for (businessInfo *business_info in VC.selectedBusinessesArray) {



    businessInfoAnnotation *businessAnnotation = [[businessInfoAnnotation alloc] init];

    businessAnnotation.businessInfoClass = business_info;

    CLGeocoder *geocoder = [[CLGeocoder alloc] init];

    [geocoder geocodeAddressString:business_info.location
                 completionHandler:^(NSArray* geocoded, NSError* error){
                     if (geocoded && geocoded.count > 0) {
                         CLPlacemark *placemark = [geocoded objectAtIndex:0];
                         CLLocation *location = placemark.location;
                         CLLocationCoordinate2D business_cords = location.coordinate;
                         businessAnnotation.coordinate = business_cords;
                     }
                 }];

    businessAnnotation.title = business_info.name;

    [businessPoints addObject:businessAnnotation];

}

[businessMap addAnnotations:businessPoints];

[businessMap setZoomEnabled:YES];

[self zoomToFitMapAnnotations:businessMap withArray:businessPoints];

Вот мой метод масштабирования:

-(void)zoomToFitMapAnnotations:(MKMapView*)mapViews withArray:(NSArray*)anAnnotationArray
{
    if([mapViews.annotations count] == 0) return;

    CLLocationCoordinate2D topLeftCoord;
    topLeftCoord.latitude = -90;
    topLeftCoord.longitude = 180;
    NSLog(@"zooming");

    CLLocationCoordinate2D bottomRightCoord;
    bottomRightCoord.latitude = 90;
    bottomRightCoord.longitude = -180;



    for(MKPointAnnotation* annotation in anAnnotationArray)
    {
        topLeftCoord.longitude = fmin(topLeftCoord.longitude, annotation.coordinate.longitude);
        topLeftCoord.latitude = fmax(topLeftCoord.latitude, annotation.coordinate.latitude);

        bottomRightCoord.longitude = fmax(bottomRightCoord.longitude, annotation.coordinate.longitude);
        bottomRightCoord.latitude = fmin(bottomRightCoord.latitude, annotation.coordinate.latitude);
    }

    MKCoordinateRegion region;
    region.center.latitude = topLeftCoord.latitude - (topLeftCoord.latitude - bottomRightCoord.latitude) * 0.5;
    region.center.longitude = topLeftCoord.longitude + (bottomRightCoord.longitude - topLeftCoord.longitude) * 0.5;
    region.span.latitudeDelta = fabs(topLeftCoord.latitude - bottomRightCoord.latitude) * 1.1;
    region.span.longitudeDelta = fabs(bottomRightCoord.longitude - topLeftCoord.longitude) * 1.1;

    region = [mapViews regionThatFits:region];
    [businessMap setRegion:region animated:YES];
}

Спасибо за помощь, спасибо. Извините, если это небрежно, это мой первый пост.

Редактировать:
Вот мой отредактированный метод геокодера согласно ответу Невана Кинга.

[geocoder geocodeAddressString:business_info.location
             completionHandler:^(NSArray* geocoded, NSError* error){
                 if (geocoded && geocoded.count > 0) {
                     CLPlacemark *placemark = [geocoded objectAtIndex:0];
                     CLLocation *location = placemark.location;
                     CLLocationCoordinate2D business_cords = location.coordinate;
                     businessAnnotation.coordinate = business_cords;

                     businessAnnotation.title = business_info.name;

                     [businessPoints addObject:businessAnnotation];

                     [businessMap addAnnotations:businessPoints];

                     [self zoomToFitMapAnnotations:businessMap withArray:businessPoints];
                 }
             }
];

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

3 ответа

Решение

Кажется, лучший способ запустить метод после того, как все аннотации были геокодированы и загружены на карту, - это запустить простой счетчик и оператор if, проверяющий номер счетчика с помощью массива.

Вот что я придумал: int pointsArrayCount = contactArray.count; NSLog(@"Count: %d", pointsArrayCount); int numberOfPoints = pointsArrayCount; NSLog(@"Счетное число: %d", numberOfPoints); я = 0;

for (contactInfo *contact_info in contactArray) {

    contatcInfoAnnotation *annotation = [[contatcInfoAnnotation alloc] init];

    annotation.contactInfoClass = contact_info;

    CLGeocoder *geocoder = [[CLGeocoder alloc] init];

    [geocoder geocodeAddressString:contact_info.address
                 completionHandler:^(NSArray* geocoded, NSError* error){
                     if (geocoded && geocoded.count > 0) {
                         CLPlacemark *placemark = [geocoded objectAtIndex:0];
                         CLLocation *location = placemark.location;
                         CLLocationCoordinate2D contact_cords = location.coordinate;
                         annotation.coordinate = contact_cords;

                         annotation.title = contact_info.name;

                         [mapPoints addObject:annotation];

                         [mapView addAnnotations:mapPoints];

                         i++;

                         NSLog(@"Count Number of Geocoded: %d", i);

                         if(i == numberOfPoints) {
                             [self zoomToFitMapAnnotations:mapView withArray:mapPoints];
                         }
                     }
                 }//end completionHandler
     ];

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

MKMapViewDelegate имеет mapView:didAddAnnotationViews: метод, который вызывается после размещения группы аннотаций на карте. Обратите внимание, что это не то же самое, что аннотации (некоторые аннотации могут не отображаться в зависимости от масштаба).

Редактировать: я только что заметил, что вы геокодировать места в первую очередь. В этом случае вам нужно будет добавить аннотации к карте в обработчике завершения геокодирования. Сделайте это в главном потоке. В вашем коде, во время звонка addAnnotations: блок завершения еще не закончен.

Вы можете использовать группу рассылки, но я считаю, что вам придется вручную использовать dispatch_group_enter и dispatch_group_leave, а не dispatch_group_async. Таким образом, вы можете войти в группу перед каждым вызовом geocodeAddressString и покинуть группу, когда закончится ее блок завершения. Когда все блоки завершения завершены, dispatch_notify вызовет ваш код для изменения размера.

Другие вопросы по тегам