Как запустить просмотр выноски MKAnnotationView, не касаясь булавки? - PullRequest
73 голосов
/ 11 июня 2009

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

Как мне это сделать? Вызов setSelected:YES в аннотации ничего не сделал. Я думаю о симуляции касания булавки, но я не знаю, как это сделать.

Ответы [ 13 ]

62 голосов
/ 13 сентября 2009

Но есть ловушка, чтобы заставить работать решение benvolioT, код

for (id<MKAnnotation> currentAnnotation in mapView.annotations) {       
    if ([currentAnnotation isEqual:annotationToSelect]) {
        [mapView selectAnnotation:currentAnnotation animated:FALSE];
    }
}

следует вызывать с - (void)mapViewDidFinishLoadingMap:(MKMapView *)mapView, и больше нигде.

Последовательность, в которой вызываются различные методы, такие как viewWillAppear, viewDidAppear из UIViewController и - (void)mapViewDidFinishLoadingMap:(MKMapView *)mapView, отличается в зависимости от того, когда карта впервые загружается в одно конкретное местоположение, и последующих раз отображается в том же месте. Это немного сложно.

34 голосов
/ 11 июня 2009

Хорошо, вот решение этой проблемы.

Для отображения выноски используйте метод MKMapView selectAnnotation:animated.

32 голосов
/ 15 ноября 2010

Предполагая, что вы хотите, чтобы был выбран последний вид аннотации, вы можете поместить код ниже:

[mapView selectAnnotation:[[mapView annotations] lastObject] animated:YES];

в делегате ниже:

- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views
{
    //Here
    [mapView selectAnnotation:[[mapView annotations] lastObject] animated:YES];
}
21 голосов
/ 27 мая 2011

Хорошо, чтобы успешно добавить выноску, вам нужно вызвать selectAnnotation: анимируется после добавления всех представлений аннотации с использованием делегата didAddAnnotationViews:

- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views{
    for (id<MKAnnotation> currentAnnotation in mapView.annotations) {       
        if ([currentAnnotation isEqual: annotationToSelect]) {
            [mapView selectAnnotation:currentAnnotation animated:YES];
        }
    }
}
12 голосов
/ 02 августа 2012

Попробовав множество ответов на эту ветку, я наконец-то придумал это. Это работает очень надежно, я еще не видел, как это не сработало:

- (void)mapView:(MKMapView *)aMapView didAddAnnotationViews:(NSArray *)views;
{
    for(id<MKAnnotation> currentAnnotation in aMapView.annotations) 
    {       
        if([currentAnnotation isEqual:annotationToSelect]) 
        {
            NSLog(@"Yay!");
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.3 * NSEC_PER_SEC), dispatch_get_current_queue(), ^
            {
                [aMapView selectAnnotation:currentAnnotation animated:YES];
            });
        }
    }
}

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

9 голосов
/ 24 августа 2009

Это не работает для меня. Я подозреваю ошибку в API MapKit.

Смотрите эту ссылку для получения информации о ком-то еще, для которого это не работает: http://www.iphonedevsdk.com/forum/iphone-sdk-development/19740-trigger-mkannotationview-callout-bubble.html#post110447

- изменить -

Хорошо, после того, как я какое-то время облажался, вот что я смог сделать:

for (id<MKAnnotation> currentAnnotation in mapView.annotations) {       
    if ([currentAnnotation isEqual:annotationToSelect]) {
        [mapView selectAnnotation:currentAnnotation animated:FALSE];
    }
}

Обратите внимание, для этого требуется реализация - (BOOL)isEqual:(id)anObject для вашего класса, реализующего протокол MKAnnotation.

6 голосов
/ 11 сентября 2009

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

[mapView selectAnnotation:[[mapView annotations] lastObject] animated:YES];

5 голосов
/ 01 сентября 2013

Проблема с вызовом selectAnnotation из - (void)mapViewDidFinishLoadingMap:(MKMapView *)mapView заключается в том, что, как следует из названия, это событие вызывается только после первоначальной загрузки MapView, поэтому вы не сможете вызвать выноску аннотации, если добавите ее после MapView завершил загрузку.

Проблема с вызовом из - (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views заключается в том, что ваша аннотация может не отображаться на экране при вызове selectAnnotation, что приведет к тому, что оно не будет иметь никакого эффекта. Даже если вы центрируете область своего MapView по координате аннотации перед добавлением аннотации, небольшой задержки, необходимой для установки области MapView, достаточно для вызова selectAnnotation до того, как аннотация будет видна на экране, особенно если вы анимируете setRegion.

Некоторые люди решили эту проблему, вызвав selectAnnotation после такой задержки:

-(void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views {
    [self performSelector:@selector(selectLastAnnotation)
        withObject:nil afterDelay:1];
}

-(void)selectLastAnnotation {
    [myMapView selectAnnotation:
        [[myMapView annotations] lastObject] animated:YES];
}

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

Я решил сделать вызов с - (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated, поскольку он гарантирует, что аннотация фактически отображается на экране (при условии, что вы установили регион MapView в качестве координаты аннотации), потому что это событие срабатывает после setRegion (и его анимация) закончена. Однако regionDidChangeAnimated запускается всякий раз, когда изменяется область вашего MapView, в том числе, когда пользователь просто перемещается по карте, поэтому вы должны убедиться, что у вас есть условие, чтобы правильно определить, когда подходящее время для запуска выноски аннотации.

Вот как я это сделал:

MKPointAnnotation *myAnnotationWithCallout;

- (void)someMethod {
    MKPointAnnotation *myAnnotation = [[MKPointAnnotation alloc] init];
    [myAnnotation setCoordinate: someCoordinate];
    [myAnnotation setTitle: someTitle];

    MKCoordinateRegion someRegion =
       MKCoordinateRegionMakeWithDistance (someCoordinate, zoomLevel, zoomLevel);

    myAnnotationWithCallout = myAnnotation;
    [myMapView setRegion: someRegion animated: YES];
    [myMapView addAnnotation: myAnnotation];
}

- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated
{
    if (myAnnotationWithCallout)
    {
        [mapView selectAnnotation: myAnnotationWithCallout animated:YES];
        myAnnotationWithCallout = nil;
    }
}

Таким образом, ваша аннотация гарантированно будет отображаться на экране в момент вызова selectAnnotation, а часть if (myAnnotationWithCallout) гарантирует, что никакая настройка региона, кроме той, которая указана в - (void)someMethod, не вызовет сноску.

5 голосов
/ 11 сентября 2010

Я внимательно прочитал API и, наконец, нашел проблему:


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

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

3 голосов
/ 30 января 2010

Из-за чего-то вроде кода, показанного benvolioT, который, как я подозреваю, существует в системе, когда я использовал selectAnnotation: animation: метод, он не показывал callOut, я догадался, что причина в том, что он уже был выбран, и он не просил MapView перерисовать callOut на карте, используя заголовок и подзаголовок аннотации.

Итак, решение состояло в том, чтобы сначала просто отменить выбор и повторно выбрать его.

Eg. Во-первых, мне нужно было сделать это в методе Apple touchMoved (т.е. как перетащить AnnotationView), чтобы скрыть callOut. (Простое использование annotation.canShowAnnotation = NO само по себе не работает, так как я подозреваю, что оно нуждается в перерисовке. Отмена выбора Annotaiton вызывает необходимое действие. Кроме того, отмена выбора одного не сделала этого трюка, callOut исчез только один раз и сразу перерисовался. Это был намек на то, что он был автоматически переизбран).

annotationView.canShowAnnotation = NO;
[mapView deselectAnnotation:annotation animated:YES];

Тогда простое использование кода ниже в методе touchEnded не вернуло callOut (аннотация к этому времени автоматически выбиралась системой, и, вероятно, перерисовка callOut никогда не происходила):

annotationView.canShowAnnotation = YES;
[mapView selectAnnotation:annotation animated:YES];

Решение было:

annotationView.canShowAnnotation = YES;
[mapView deselectAnnotation:annotation animated:YES];
[mapView selectAnnotation:annotation animated:YES];

Это просто выкупило callOut, по-видимому, оно заново запустило процесс перерисовки callOut с помощью mapView.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...