【问题标题】:Why calloutAccessoryControlTapped is called for tap on annotation view also?为什么还调用 calloutAccessoryControlTapped 来点击注释视图?
【发布时间】:2016-04-05 17:07:22
【问题描述】:

我的视图控制器上有一个地图,但我不知道为什么,但是当我点击注释视图时也会调用委托 calloutAccessoryControlTapped,而不仅仅是在我点击详细信息关闭时 .那么为什么会有这种行为呢?

import UIKit
import MapKit

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

}

【问题讨论】:

    标签: ios swift mapkit


    【解决方案1】:

    根据 Apple 开发者文档:

    附件视图包含自定义内容并位于 注释标题文本的一侧。如果您指定的视图是 UIControl 类的后代,地图视图将此方法作为 方便用户点击您的视图。你可以使用这个方法 响应点击并执行与该点击相关的任何操作 控制。例如,如果您的控件显示附加信息 关于注释,您可以使用此方法呈现模态 包含该信息的面板。

    如果您的自定义附件视图不是 UIControl 的后代 类,地图视图不调用该方法。

    那么你的附件视图是从 UIControl 继承的吗?

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

    【讨论】:

    • 对不起,但我看不出重点,文档还说:告诉代表用户点击了注释视图的附件按钮之一。因此,我希望仅针对按钮上的点击事件调用委托,而不是针对整个注释视图。
    • 它说:“您指定的视图是 UIControl 类的后代,每当用户点击您的视图时,地图视图都会调用此方法以方便您。”那么你的附件视图是从 UIControl 继承的吗?
    【解决方案2】:

    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")
            }
        }
    }
    

    【讨论】:

      【解决方案3】:

      这取决于您在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 以来标注按钮工作方式的变化有关。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-01-07
        • 2022-09-29
        • 1970-01-01
        • 1970-01-01
        • 2018-10-05
        • 1970-01-01
        相关资源
        最近更新 更多