为什么调用calloutAccessoryControlTapped也可以点击注释视图?

时间:2016-04-05 17:07:22

标签: ios swift mapkit

我的视图控制器上有一张地图,我不知道为什么,但是当我点击注释视图时,也会调用代理calloutAccessoryControlTapped ,而不仅仅是当我点击详细信息时 STRONG>。那为什么会这样呢?

import UIKit
import MapKit

extension MapVC: MKMapViewDelegate, CLLocationManagerDelegate
{    
    func mapView(mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl)
    {
        ...
    }

}

3 个答案:

答案 0 :(得分:1)

根据Apple开发人员文档:

  

附件视图包含自定义内容并位于其中之一   注释标题文本的一面。如果您指定的视图是   UIControl类的后代,地图视图将此方法称为   用户点击视图时的便利性。您可以使用此方法   响应点击并执行与之相关的任何操作   控制。例如,如果您的控件显示其他信息   关于注释,您可以使用此方法来呈现模态   有这些信息的小组。

     

如果您的自定义附件视图不是UIControl的后代   class,map视图不会调用此方法。

您的配件视图是否继承自UIControl?

参考: https://developer.apple.com/library/ios/documentation/MapKit/Reference/MKMapViewDelegate_Protocol/#//apple_ref/occ/intfm/MKMapViewDelegate/mapView:annotationView:calloutAccessoryControlTapped

答案 1 :(得分:0)

Massimo Polimeni似乎是正确的。 rightCalloutAccessoryView似乎有问题,而leftCalloutAccessoryView则没有问题。

下面的代码(带有leftCalloutAccessoryView)可以正常工作。如果您点击左侧附件,它将打印“已选择左侧附件”。如果您点击标注标题,它将不会打印任何内容。

如果您使用rightCalloutAccessoryView(在下面注释掉)并点击右边的附件,它将打印“选择了右边的附件”。 如果您点击标注标题,它还会打印“已选择正确的附件” 。这似乎不正确。

import UIKit
import MapKit

class ViewController: UIViewController, MKMapViewDelegate {

    @IBOutlet weak var mapView: MKMapView!

    override func viewDidLoad() {
        super.viewDidLoad()

        let annotation = MKPointAnnotation()
        annotation.coordinate = CLLocationCoordinate2D(latitude: 50.29, longitude: -107.79)
        annotation.title = "Swift Current"

        mapView.addAnnotation(annotation)
        mapView.mapType = .standard
        mapView.delegate = self
        mapView.region = MKCoordinateRegion(
            center: CLLocationCoordinate2D(latitude: annotation.coordinate.latitude,
                                           longitude: annotation.coordinate.longitude),
            span: MKCoordinateSpan(latitudeDelta: 1.0, longitudeDelta: 1.0)
        )
    }

    func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
        let reuseId = "Annotation"
        var view = mapView.dequeueReusableAnnotationView(withIdentifier: reuseId)
        if view == nil {
            view = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
            view?.canShowCallout = true
            view?.leftCalloutAccessoryView = UIButton(type: .detailDisclosure)
            //view?.rightCalloutAccessoryView = UIButton(type: .detailDisclosure)
        } else {
            view?.annotation = annotation
        }
        return view
    }

    func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
        if control == view.leftCalloutAccessoryView {
            print("left accessory selected")
        } else if control == view.rightCalloutAccessoryView {
            print("right accessory selected")
        }
    }
}

答案 2 :(得分:0)

这取决于您在rightCalloutAccessoryView上设置的按钮类型。例如。如果您使用:

[UIButton buttonWithType:UIButtonTypeDetailDisclosure];

然后同时点击标注和按钮都导致calloutAccessoryControlTapped被该按钮调用。但是,如果您使用:

[UIButton systemButtonWithImage:[UIImage systemImageNamed:@"info.circle"] target:nil action:nil];

然后,只有点击按钮才能使用,点击标注将被禁用。

如果您有一个自定义按钮,并且想要第一个行为,那么可以创建一个按钮子类并执行以下操作:

@interface UIButton2 : UIButton

@end

@implementation UIButton2

- (id)_mapkit_accessoryControlToExtendWithCallout{
    return self;
}

@end

此私有方法决定了按钮是否也可以用于点击标注(使用Hopper来学习)。默认实现会检查self.buttonType来决定。

更明智的方法是从显示按钮开始并更改其图像,例如

UIButton *button = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
UIImage *image = [UIImage systemImageNamed:@"chevron.right" withConfiguration:[UIImageSymbolConfiguration configurationWithScale:UIImageSymbolScaleSmall];
[button setImage:image forState:UIControlStateNormal];

自iOS 6以来,这种怪异行为在很大程度上可能是因为标注按钮的工作方式发生了变化。