title: Swift GestureRecognizers with MKMapKit - Drop pin and drag
body: <p>I am trying to use a number of <code>UIGestureReconizers</code> with an <code>MKMapView</code> onto which the user can drop a pin and drag it around. It has a <code>callout</code>. I am implementing this in a <code>TabbarController</code> and also within a <code>NavigationController</code>. I currently have:</p>
  
  <p>1) A <code>PanGestureRecognizer</code> animates the Tabbar and Navigation item off the screen. This works fine without interfering with panning the map.</p>
  
  <p>2) A <code>TapGestureRecognizer</code> set to one tap animates the two items from 1) back onto the screen.</p>
  
  <p>3) A <code>TapGestureRecognizer</code> set to two taps allows the underlying <code>MKMapView</code> zoom functionality to work. This <code>GestureRecognizer's</code> <code>delegate</code> has gestureRecognizer.<code>shouldRecognizeSimultaneouslyWithGestureRecognizer</code> set to <code>true</code></p>
  
  <p>These are setup in <code>viewDidLoad</code> as follows:</p>
  
  <pre><code> // This sets up the pan gesture recognizer to hide the bars from the UI.
      let panRec: UIPanGestureRecognizer = UIPanGestureRecognizer(target: self, action: "didDragMap:")
      panRec.delegate = self
      mapView.addGestureRecognizer(panRec)
  
      // This sets up the tap gesture recognizer to un-hide the bars from the UI.
      let singleTap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "didTapMap:")
      singleTap.delegate = self
      singleTap.numberOfTapsRequired = 1
      singleTap.numberOfTouchesRequired = 1
      mapView.addGestureRecognizer(singleTap)
  
      // This sets up the double tap gesture recognizer to enable the zoom facility.
      // In order to pass double-taps to the underlying `MKMapView` the delegate for this recognizer (self) needs to return true from
      // gestureRecognizer.shouldRecognizeSimultaneouslyWithGestureRecognizer
      let doubleTap: UITapGestureRecognizer = UITapGestureRecognizer()
      doubleTap.numberOfTapsRequired = 2
      doubleTap.numberOfTouchesRequired = 1
      doubleTap.delegate = self
      mapView.addGestureRecognizer(doubleTap)
  
  // This delays the single-tap recognizer slightly and ensures that it will NOT fire if there is a double-tap
      singleTap.requireGestureRecognizerToFail(doubleTap)
  </code></pre>
  
  <p>My problem occurs when I try to implement a <code>UILongPressGestureRecognizer</code> to allow the dropping of a pin onto the map. I'm trying to use the following added to <code>viewDidLoad</code>:</p>
  
  <pre><code>// This sets up the long tap to drop the pin.
      let longTap: UILongPressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: "didLongTapMap:")
      longTap.delegate = self
      longTap.numberOfTapsRequired = 0
      longTap.minimumPressDuration = 0.5
      mapView.addGestureRecognizer(longTap)
  </code></pre>
  
  <p>This is my action method:</p>
  
  <pre><code>func didLongTapMap(gestureRecognizer: UIGestureRecognizer) {
      // Get the spot that was tapped.
      let tapPoint: CGPoint = gestureRecognizer.locationInView(mapView)
      let touchMapCoordinate: CLLocationCoordinate2D = mapView.convertPoint(tapPoint, toCoordinateFromView: mapView)
  
      var viewAtBottomOfHierarchy: UIView = mapView.hitTest(tapPoint, withEvent: nil)
      if let viewAtBottom = viewAtBottomOfHierarchy as? MKPinAnnotationView {
          return
      } else {
          if .Began == gestureRecognizer.state {
              // Delete any existing annotations.
              if mapView.annotations.count != 0 {
                  mapView.removeAnnotations(mapView.annotations)
              }
  
              annotation = MKPointAnnotation()
              annotation.coordinate = touchMapCoordinate
  
              mapView.addAnnotation(annotation)
              _isPinOnMap = true
  
              findAddressFromCoordinate(annotation.coordinate)
              updateLabels()
          }
      }
  }
  </code></pre>
  
  <p>This does indeed allow a pin to be dropped on a long tap and a single tap will display the callout BUT a second tap to hold and drag causes a second pin to drop if the drag isn't started sufficiently quickly. This second pin drops into the space the previous pin was hovering in and can be dragged by the user, but the new pin dropping is awkward and wrong looking.</p>
  
  <p>I'm trying to use the line:</p>
  
  <pre><code>if let viewAtBottom = viewAtBottomOfHierarchy as? MKPinAnnotationView {
  </code></pre>
  
  <p>to return the tap to the <code>MKMapView</code> and prevent another pin being dropped but the return never gets called even though a breakpoint on this line shows viewAtBottom is of type <code>MapKit.MKPinAnnotationView</code>. Any ideas where I'm going wrong?</p>