PeculiarProgrammer
PeculiarProgrammer

Reputation: 11

Adding touch or button to UIView as custom callout in MapKit not triggering action

I have a map created with MapKit with custom annotations and a custom view used as a callout. tapping on any pin will pop the callout with address info. it works great. I am now trying to open maps when the callout is tapped but it's not accepting touches. I tried adding a button but the button action doesn't get triggered either. Any thoughts on how I can get the callout to respond, in an way?

P.S - I need to support iOS 13

class CustomCallout: UIView {
   @IBOutlet weak var container: UIView!
   @IBOutlet weak var distanceView: UIView!
   @IBOutlet weak var nameLabel: UILabel!
   @IBOutlet weak var address1Label: UILabel!
   @IBOutlet weak var address2Label: UILabel!
   @IBOutlet weak var cityStateZipLabel: UILabel!
   @IBOutlet weak var distanceLabel: UILabel!
   
   
   // tried this too and nothing
   override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
      guard !clipsToBounds && !isHidden && alpha > 0 else { return nil }
      for member in subviews.reversed() {
         let subPoint = member.convert(point, from: self)
         guard let result = member.hitTest(subPoint, with: event) else { 
            continue
         }
         return result
      }
      return nil
   }
   
   
   func configure(location: location, distance: String) {

      // removed code for creating labels here to save space
      
      ...
      
      // does not work
      let tap = UITapGestureRecognizer(target: self, action: #selector(loadDirections))
      container.isMultipleTouchEnabled = true
      container.addGestureRecognizer(tap)
   }

   private func setupUI() {
      Bundle.main.loadNibNamed(className, owner: self, options: nil)
      addSubview(contentView)
      contentView.frame = self.bounds
      contentView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
   }
   
   @objc func loadDirections() {
      print("loading directions from tap")
   }
   
   @IBAction func openMap(_ sender: Any) {
      print("loading directions from button")
   }
   
   // MARK: Init
   
   override init(frame: CGRect) {
      super.init(frame: frame)
      setupUI()
   }
   
   required init?(coder: NSCoder) {
      super.init(coder: coder)
      setupUI()
   }
}

// delegate when pin is selected - shows callout successfully
func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
   
   // thought this might be the culprit - but no
//      view.subviews.filter { $0 is RetailersCallout }.forEach {
//         $0.removeFromSuperview()
//      }
      
      if let pin = view.annotation as? PinPointAnnotation {
         if let location = viewModel.locations.value.filter({
            $0.locationId == pin.tag
         }).first {
            let callout = CustomCallout()
            let location = CLLocation(
               latitude: Double(location.latitude) ?? 0,
               longitude: Double(location.longitude) ?? 0
            )
            var miles = "200" // testing
            
            callout.configure(location: location, distance: miles)
            
            view.addSubview(callout)
            
            // tried adding it here too
            let tap = UITapGestureRecognizer(target: self, action: #selector(loadDirections))
            callout.addGestureRecognizer(tap)
            callout.isMultipleTouchEnabled = true
            
            // using TinyConstraints
            callout.centerX(to: view)
            callout.centerY(to: view)
            callout.bottomToTop(of: view)
            
            // animate
            callout.alpha = 0.0
            callout.contentScaleFactor = 0.0
            UIView.animate(withDuration: 0.2) {
               callout.alpha = 1.0
               callout.contentScaleFactor = 1.0
               
               self.centerOnLoction(location: storeLocation)
            }
         }
      }
   }

Upvotes: 0

Views: 28

Answers (0)

Related Questions