Search code examples
iosswiftmkmapviewcllocationmanageruserlocation

How to show in which side user turn phone, if I show user location using MKMapView


I want to show into which side the user turns the phone, like on MapView, and can't understand how to do that, I have tried to use these options, but they can't help me:

mapView.showsUserLocation = true
mapView.isRotateEnabled = true
mapView.isPitchEnabled = true
mapView.showsCompass = true
mapView.userTrackingMode = .follow

enter image description here


Solution

  • The problem was solved by this answer and the help of Asteroid, appreciated your support. My code:

    import UIKit
    import MapKit
    import CoreLocation
    
    class MapScreen: UIViewController, MKMapViewDelegate {
        
        
        let locationManager = CLLocationManager()
        var location: CLLocation!
        
        lazy var mapView: MKMapView = {
            let map = MKMapView()
            map.delegate = self
            
            return map
        }()
        
        override func viewDidLoad() {
            super.viewDidLoad()
            
            view.addSubview(mapView)
            mapView.frame = view.frame
            
            initUserLocation()
        }
        
        var headingImageView: UIImageView?
        var userHeading: CLLocationDirection?
        
        func mapView(_ mapView: MKMapView, didAdd views: [MKAnnotationView]) {
            if views.last?.annotation is MKUserLocation {
                addHeadingView(toAnnotationView: views.last!)
            }
        }
        
        func addHeadingView(toAnnotationView annotationView: MKAnnotationView) {
            if headingImageView == nil {
                let image = UIImage(named: "iconU")
                headingImageView = UIImageView(image: image)
                headingImageView!.frame = CGRect(x: (annotationView.frame.size.width - image!.size.width)/2, y: (annotationView.frame.size.height - image!.size.height)/2, width: image!.size.width, height: image!.size.height)
                annotationView.insertSubview(headingImageView!, at: 0)
                headingImageView!.isHidden = true
            }
        }
    }
    
    extension MapScreen: CLLocationManagerDelegate {
        
        
        func initUserLocation() {
            locationManager.delegate = self
            locationManager.desiredAccuracy = kCLLocationAccuracyBest
            locationManager.requestWhenInUseAuthorization()
            locationManager.startUpdatingLocation()
            locationManager.startUpdatingHeading()
            mapView.showsUserLocation = true
            //        mapView.userTrackingMode = .followWithHeading
        }
        
        func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
            self.location = locations.last as CLLocation?
        }
        
        func locationManager(_ manager: CLLocationManager, didUpdateHeading newHeading: CLHeading) {
            if newHeading.headingAccuracy < 0 { return }
            
            let heading = newHeading.trueHeading > 0 ? newHeading.trueHeading : newHeading.magneticHeading
            userHeading = heading
            updateHeadingRotation()
        }
        
        
        func updateHeadingRotation() {
            if let heading = userHeading,
               let headingImageView = headingImageView {
                
                headingImageView.isHidden = false
                let rotation = CGFloat(heading/180 * Double.pi)
                headingImageView.transform = CGAffineTransform(rotationAngle: rotation)
            }
        }
    }