Search code examples
swiftuiimageviewmapkitmapkitannotation

MapKit functionality on a UIImage, dropping pins/Annotation


I am trying to use the existing MapKit functionality on an image. What I am trying to achieve is to drop pins on an image and maybe add notes on these pins. I have managed to give the user the possibility to add a pin dynamically with a longGesture but I don't know how to achieve the same on an image.

My code is as follows:

import UIKit
import MapKit

class ViewController: UIViewController , MKMapViewDelegate {

    @IBOutlet weak var mapView: MKMapView!
    var keyLat:String = "49.2768"
    var keyLon:String = "-123.1120"
    @IBOutlet weak var image: UIImageView!
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        mapView.delegate = self
        
        let longPressRecogniser = UILongPressGestureRecognizer(target: self, action: #selector(self.handleTap(_:)))
        longPressRecogniser.minimumPressDuration = 0.5
        mapView.addGestureRecognizer(longPressRecogniser)
        
        mapView.mapType = MKMapType.standard
        
        let location = CLLocationCoordinate2D(latitude: CLLocationDegrees(keyLat.toFloat()),longitude: CLLocationDegrees(keyLon.toFloat()))
        
        let span = MKCoordinateSpan(latitudeDelta: 0.05, longitudeDelta: 0.05)
        let region = MKCoordinateRegion(center: location, span: span)
        mapView.setRegion(region, animated: true)
        
        let annotation = MKPointAnnotation()
        annotation.coordinate = location
        annotation.title = "MY Pin"
        annotation.subtitle = "On the Map"
        mapView.addAnnotation(annotation)
    }

    
    @objc func handleTap(_ gestureReconizer: UILongPressGestureRecognizer)
    {
        
        let location = gestureReconizer.location(in: mapView)
        let coordinate = mapView.convert(location,toCoordinateFrom: mapView)
        
        // Add annotation:
        let annotation = MKPointAnnotation()
        annotation.coordinate = coordinate
        annotation.title = "latitude:" + String(format: "%.02f",annotation.coordinate.latitude) + "& longitude:" + String(format: "%.02f",annotation.coordinate.longitude)
        mapView.addAnnotation(annotation)
        
    }
    
    
    var selectedAnnotation: MKPointAnnotation?
    
    func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
        
        let latValStr : String = String(format: "%.02f",Float((view.annotation?.coordinate.latitude)!))
        let lonvalStr : String = String(format: "%.02f",Float((view.annotation?.coordinate.longitude)!))
        
        print("latitude: \(latValStr) & longitude: \(lonvalStr)")
    }
    
}

any help will be really appreciated. Thanks George


Solution

  • The same can be achieved by following the same procedure with a few tweaks here and there. I've made a sample ViewController that demonstrates how you can add pointers (UIViews in this case) into a UIImageView.

    class ViewController: UIViewController {
    
        @IBOutlet weak var imageView: UIImageView! // Image view
    
        lazy var longPress = UILongPressGestureRecognizer(target: self, action: #selector(didLongPressScreen)) // long press gesture
    
        // MARK: LifeCycle
        override func viewDidLoad() {
            super.viewDidLoad()
        }
    
        override func viewDidAppear(_ animated: Bool) {
            super.viewDidAppear(animated)
            setup()
        }
    
        // MARK: Functions
        private func setup() {
            imageView.image = UIImage(named: "photo")
    
            imageView.addGestureRecognizer(longPress) // Adding gesture recognizer 
            imageView.isUserInteractionEnabled = true // ImageViews are not user interactive by default
    
        }
    
        // UILongPressGestureRecognizer Action
        @objc func didLongPressScreen(_ sender: UILongPressGestureRecognizer) {
            let location = sender.location(in: self.view) //Getting location
    
            DispatchQueue.main.async {
                let pointer = UIView(frame: CGRect(x: 0, y: 0, width: 20, height: 20))
                pointer.backgroundColor = .red
                pointer.center = location // Setting the center of the view to the x,y coordinates of the long press
                self.view.addSubview(pointer) // Adding the UIView to the view
            }
        }
    }
    

    The most important part of this is to enable the user interaction for the UIImageView as its. isUserInteractionEnabled is set to false by default. The output of the above can be seen below,

    enter image description here