Требуется: как надежно, последовательно выбирать аннотацию MKMapView

После вызова MKMapView setCenterCoordinate: анимированный: метод (без анимации), я бы хотел вызвать selectAnnotation: animated: (с анимацией), чтобы аннотация выскочила из нон-центрированной кнопки.

Пока я просто смотрю карту mapViewDidFinishLoadingMap: а затем выберите аннотацию. Однако это проблематично. Например, этот метод не вызывается, когда нет необходимости загружать дополнительные данные карты. В этих случаях моя аннотация не выбрана. :(

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

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

Любые идеи о том, как это сделать или как иначе (надежно) выбрать аннотацию после переориентации вида карты на координате, где живет эта аннотация?

Ключи оценены - спасибо!

Ответ 1

Я столкнулся с той же проблемой, но нашел то, что кажется надежным и разумным решением:

  • Реализовать метод делегата mapView: didAddAnnotationViews:. Когда я попытался выбрать аннотацию непосредственно в методе делегата, выноска опустилась с помощью булавки! Это выглядело странно, поэтому я добавляю небольшую задержку в полсекунды.

    -(void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views {
        [self performSelector:@selector(selectInitialAnnotation)
              withObject:nil afterDelay:0.5];
    }
    
  • Выберите начальную аннотацию, как и следовало ожидать, но вызовите selectAnnotation: animated;

    -(void)selectInitialAnnotation {
        [self.mapView selectAnnotation:self.initialAnnotation animated:YES];
    }
    

Кажется, что selectAnnotation:animated: не вызывается при некоторых условиях. Сравните с Документы MKMapView:

Если указанная аннотация не находится на экране, и, следовательно, не имеют связанный аннотация, этот метод не имеет эффекта.

Ответ 2

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

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

Сначала перейдите к центральной координате аннотации. Скажем, объект аннотации называется thePin.

- (void)someMethod {
    [map setCenterCoordinate:thePin.coordinate animated:YES];
}

Затем в методе regionDidChange выберите эту аннотацию.

- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated {
    [map selectAnnotation:thePin animated:YES];
}

Ответ 3

Что сработало для меня, это вызов selectAnnotation:animated: из метода mapView:didAddAnnotationViews::

- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views;
{
    [mapView selectAnnotation:[[mapView annotations] lastObject] animated:YES];
}

Документация Apple на тот же здесь.

Обратите внимание, что у меня была только одна аннотация на карте, поэтому [[mapView annotations] lastObject] была в порядке для моих целей. Ваш пробег может отличаться.

Ответ 4

Ну просто FYI, это то, что говорят документы,

Если указанная аннотация не находится на экране, и, следовательно, не имеют связанный аннотация, этот метод не имеет эффекта.

Поэтому, если я хочу вызвать setCenterCoordinate:animated: или setRegion:animated:, а затем я хочу выбрать аннотацию по вызову, selectAnnotation:animated:, аннотация не будет выбрана, а выноска не будет отображаться с учетом того же самого причина, упомянутая выше в документах, так что было бы здорово иметь что-то вроде setCenterCoordinate:animated:ComletionBlock, но ее не было..! Способ, который работал у меня, как показано ниже,

 [UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionBeginFromCurrentState|UIViewAnimationOptionCurveEaseInOut animations:^{
        [self.mapView setCenterCoordinate:location.coordinate animated:YES];
    } completion:^(BOOL finished) {
        [self.mapView selectAnnotation:location animated:YES];
    }];

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

Ответ 5

У меня была аналогичная проблема. Я использовал MKPinAnnotationView по умолчанию с animatesDrop: YES. После того, как я добавил аннотации к MKMapView, я делал это:

[mapView selectAnnotation:[mapView.annotations objectAtIndex:1] animated:YES]

который в логике моей программы должен выбрать ближайшую аннотацию. Это не сработало. Я выяснил причину: на момент выбора этого выбора был показан аннотационный вид, из-за анимации опускания булавки. Итак, все, что я сделал, - это установить таймер, чтобы выбрать аннотацию через секунду. Это взлом, но он работает. Я не уверен, что это будет работать в любой ситуации, например, в 3G против 3G. Было бы лучше выяснить правильную функцию обратного вызова, чтобы поместить ее.

selectTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self
               selector:@selector(selectClosestAnnotation) userInfo:nil
               repeats:NO];

- (void)selectClosestAnnotation {
    [mapView selectAnnotation:[mapView.annotations objectAtIndex:1]
             animated:YES];
}

Ответ 6

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

  • Использование метода делегата mapView:didAddAnnotationViews:.

    Это не сработало для меня, потому что если указанная аннотация не является экранной и поэтому не имеет связанного представления аннотации, этот метод не имеет никакого эффекта.

  • Использование метода делегата mapViewDidFinishLoadingMap:.

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

Решение:

Джон Блэкберн был очень близок, но без метода mapView:didAddAnnotationViews:. Я просто называю свой собственный метод selectAnnotation:, прежде чем добавлять аннотацию с задержкой:
[self.mapView addAnnotation:ann];
[self performSelector:@selector(selectAnnotation:) withObject:ann afterDelay:0.5];

И вот что я делаю в моем методе selectAnnotation::

- (void)selectAnnotation:(id < MKAnnotation >)annotation
{
   [self.mapView selectAnnotation:annotation animated:YES];
}

Протестировано на двух iPhone 3GS (iOS 5 и 6) и iPhone 5.