Как получить событие click с кнопки, добавленной над MKAnnotationView

Кто-нибудь знает, есть ли способ получить событие click из button, добавленного в MKAnnotationView, этот button используется как метка, чтобы отображать имя каждого вывода на map, теперь я чтобы показать пользовательский view (который содержит изображение, текст....), когда нажимается pin, поэтому мне нужно сделать то же самое при нажатии кнопки (метки).

Спасибо за любые советы, которые вы можете предоставить.

для button в MKAnnotationView:

UIButton * pinButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 140, 28)];
[pinButton.titleLabel setTextColor:[UIColor colorWithRed:255/255.0 green:255/255.0 blue:255/255.0 alpha:1]]; 
[pinButton setCenter:CGPointMake(pinAnnotationView.center.x + 70, pinAnnotationView.center.y + 10)]; 
[pinButton addTarget:self action:@selector(pinLabelClicked) forControlEvents:UIControlEventTouchUpInside]; 
[pinAnnotationView addSubView:pinButton]; 
[pinButton setUserInteractionEnabled:YES];

Ответы

Ответ 1

Стандартный подход к пользовательскому интерфейсу состоит в том, чтобы использовать вид выноска и добавить кнопку аксессуара в качестве прогрммера.

Однако, если вы должны добавить кнопку непосредственно в MKAnnotationView, проблемы с вашим подходом состоят в том, что кадр MKPinAnnotationView по умолчанию (который не может быть легко изменен) меньше, чем кнопка, которую вы добавляете большая часть кнопки не будет реагировать на касания, и даже если вы переключитесь на использование MKAnnotationView и увеличьте размер кадра, MKMapView не позволит кнопке получить какие-либо штрихи.

Что вам нужно сделать, это добавить кнопку UITapGestureRecognizer к кнопке (используйте метод действия gesture handler вместо addTarget на кнопке) и добавьте кнопку в обычный MKAnnotationView с соответствующим размером кадра вместо of MKPinAnnotationView.

Пример:

- (MKAnnotationView *)mapView:(MKMapView *)mapView 
        viewForAnnotation:(id<MKAnnotation>)annotation
{
    MKAnnotationView *annView = (MKAnnotationView *)[mapView 
            dequeueReusableAnnotationViewWithIdentifier: @"pin"];
    if (annView == nil)
    {
        annView = [[[MKAnnotationView alloc] initWithAnnotation:annotation 
                      reuseIdentifier:@"pin"] autorelease];

        annView.frame = CGRectMake(0, 0, 200, 50);

        UIButton *pinButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
        pinButton.frame = CGRectMake(0, 0, 140, 28);
        pinButton.tag = 10;

        UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] 
            initWithTarget:self action:@selector(handlePinButtonTap:)];
        tap.numberOfTapsRequired = 1;
        [pinButton addGestureRecognizer:tap];
        [tap release];

        [annView addSubview:pinButton]; 
    }

    annView.annotation = annotation;

    UIButton *pb = (UIButton *)[annView viewWithTag:10];
    [pb setTitle:annotation.title forState:UIControlStateNormal];

    return annView;
}

- (void) handlePinButtonTap:(UITapGestureRecognizer *)gestureRecognizer 
{
    UIButton *btn = (UIButton *) gestureRecognizer.view;
    MKAnnotationView *av = (MKAnnotationView *)[btn superview];
    id<MKAnnotation> ann = av.annotation;
    NSLog(@"handlePinButtonTap: ann.title=%@", ann.title);
}


Обратите внимание, что это предотвратит запуск метода отображения didSelectAnnotationView делегата. Если вам нужен этот метод для запуска (в дополнение к методу обработчика жестов кнопки), добавьте следующее:

//in the view controller interface:
@interface YourVC : UIViewController <UIGestureRecognizerDelegate>

//where the UITapGestureRecognizer is created:
tap.delegate = self;

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer 
        shouldRecognizeSimultaneouslyWithGestureRecognizer
            :(UIGestureRecognizer *)otherGestureRecognizer
{
    return YES;
}

Ответ 2

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

-(MKAnnotationView *)mapView:(MKMapView *)map 
        viewForAnnotation:(StationItem*)annotation
{
    static NSString *AnnotationViewID = @"stationViewId";

    if ([annotation isKindOfClass:[MKUserLocation class]]) {
        return nil;  // use default user location view
    }

    MKPinAnnotationView *annotationView = 
        (MKPinAnnotationView*) [mapView dequeueReusableAnnotationViewWithIdentifier:AnnotationViewID];

    if (annotationView == nil) {
        // if an existing pin view was not available, create one
        annotationView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:AnnotationViewID] autorelease];

        // add rightAccessoryView
        UIButton* aButton = [UIButton buttonWithFrame:CGRectMake(0, 0, 75, 30)];
        [aButton setTitle:@"Directions" forState:UIControlStateNormal];
        annotationView.rightCalloutAccessoryView = aButton;
    }

    annotationView.annotation = annotation;
    annotationView.canShowCallout = YES;
    annotationView.animatesDrop   = NO;

    return annotationView;
}

После этого вам нужно реализовать MKMapViewDelegate для обработки обратного вызова делегату при нажатии кнопки:

- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control

Ответ 3

попробуйте передать штрихи в подвью:

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
 [pinButton touchesEnded:touches withEvent:event];
}

Я удивлен, что у вас есть проблема, хотя если ваш buttonView находится впереди? попробуйте убедиться, что это: [self bringSubviewToFront: pinButton];