Как вызвать отображение точки вызова MKAnnotationView без касания булавки?

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

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

Ответ 1

Хорошо, здесь решение этой проблемы.

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

Ответ 2

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

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

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

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

Ответ 3

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

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

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

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

Ответ 4

Хорошо, чтобы успешно добавить Callout, вы должны вызвать 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];
        }
    }
}

Ответ 5

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

- (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];
            });
        }
    }
}

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

Ответ 6

Это не работает для меня. Я подозреваю ошибку в 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 для вашего класса, который реализует протокол MKAnnation.

Ответ 7

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

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

Ответ 8

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


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

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

Ответ 9

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

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

Ответ 10

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

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

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

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

Затем просто используя приведенный ниже код touchEnded метод не возвратил callOut (аннотация была автоматически выбрана системой к тому времени и, по-видимому, перерисовка вызоваOut never occrrs):

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 и попытаюсь сделать это сам, на данном этапе это немного лишнее.

Ответ 11

Ответ Стива дал мне понять, что selectAnnotation нужно вызывать из метода mapViewDidFinishLoadingMap. К сожалению, я не могу проголосовать, но я хочу сказать спасибо.

Ответ 12

Сброс аннотаций также приведет к выносу на передний план.

    [mapView removeAnnotation: currentMarker];
    [mapView addAnnotation:currentMarker];

Ответ 13

Просто добавьте [mapView selectAnnotation: point animated: YES];