Kevin
Kevin

Reputation: 1189

Swift MkMapView Map is always centered around current location

Currently, my code drops a pin on the user's current location. There is one small problem when I try to move the map around, because the view will shift back and be centered around that current location pin. I want the user be able to navigate the map and move it around, and if the user switches view controllers (goes to another tab) and comes back, the map will be centered around the user location pin. I have been trying to modify this code to do this, but I have not had any luck where to start.

import UIKit
import MapKit
import CoreLocation
let newPin = MKPointAnnotation()

class MapVC: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {



@IBOutlet weak var map: MKMapView!

let locationManager =  CLLocationManager()

override func viewDidLoad() {
    super.viewDidLoad()

    // User's location

    locationManager.delegate = self
    locationManager.desiredAccuracy = kCLLocationAccuracyBest
    if #available(iOS 8.0, *) {
        locationManager.requestAlwaysAuthorization()
    } else {
        // Fallback on earlier versions
    }
    locationManager.startUpdatingLocation()


    // add gesture recognizer
    let longPress = UILongPressGestureRecognizer(target: self, action: #selector(MapVC.mapLongPress(_:))) // colon needs to pass through info
    longPress.minimumPressDuration = 1.5 // in seconds
    //add gesture recognition
    map.addGestureRecognizer(longPress)
}

// func called when gesture recognizer detects a long press

func mapLongPress(_ recognizer: UIGestureRecognizer) {

    print("A long press has been detected.")

    let touchedAt = recognizer.location(in: self.map) // adds the location on the view it was pressed
    let touchedAtCoordinate : CLLocationCoordinate2D = map.convert(touchedAt, toCoordinateFrom: self.map) // will get coordinates

    let newPin = MKPointAnnotation()
    newPin.coordinate = touchedAtCoordinate
    map.addAnnotation(newPin)


}

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {


    map.removeAnnotation(newPin)

    let location = locations.last! as CLLocation

    let center = CLLocationCoordinate2D(latitude: location.coordinate.latitude, longitude: location.coordinate.longitude)
    let region = MKCoordinateRegion(center: center, span: MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01))

    //set region on the map
    map.setRegion(region, animated: true)

    newPin.coordinate = location.coordinate
    map.addAnnotation(newPin)





}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}


}

Upvotes: 1

Views: 789

Answers (1)

Dhruv Narayan Singh
Dhruv Narayan Singh

Reputation: 655

You can use custom location manager class and call the singleton function in didfinishlaunching with option and save latitude and longitude in UserDefault .Set camera position in viewDidLoad for mapView class

1.Make singleton class

var locationShareInstance:locationManagerClass = locationManagerClass()

class locationManagerClass: NSObject, CLLocationManagerDelegate, WebServiceDelegate , UIAlertViewDelegate
{
    var locationManager = CLLocationManager()
    class func sharedLocationManager() -> locationManagerClass
    {
        locationShareInstance = locationManagerClass()
        return locationShareInstance
    }

    func startStandardUpdates() {

        locationManager.delegate = self
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        locationManager.activityType = .automotiveNavigation
        locationManager.distanceFilter = 10
        locationManager.pausesLocationUpdatesAutomatically = false

        if (Bundle.main.object(forInfoDictionaryKey: "NSLocationWhenInUseUsageDescription") != nil) {
            locationManager.requestWhenInUseAuthorization()
        }

        locationManager.startUpdatingLocation()

    }

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        // If it's a relatively recent event, turn off updates to save power.
        let location: CLLocation = locations.last!
        let strLocation = "\(location.coordinate.latitude)"
        if strLocation == "" {

        }else{
        UserDefaults.standard.set("\(location.coordinate.latitude)", forKey: "lat")
        UserDefaults.standard.set("\(location.coordinate.longitude)", forKey: "long")
        UserDefaults.standard.synchronize()
            debugPrint("Spedd: \(location.speed)")
//        self.updateLocationToServer()
            self.stopStandardUpdate()
        }
    }

    func stopStandardUpdate(){
        locationManager.stopUpdatingLocation()
    }


//MARK:- WHEN DENIED

func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
    if status == CLAuthorizationStatus.denied {

        NSLog("DENIAL")

        UserDefaults.standard.set("\(0.0)", forKey: "lat")
        UserDefaults.standard.set("\(0.0)", forKey: "long")

        self.generateAlertToNotifyUser()
    }
}

func generateAlertToNotifyUser() {

    if CLLocationManager.authorizationStatus() == CLAuthorizationStatus.notDetermined{

        var title: String
        title = ""
        let message: String = "Location Services are not able to determine your location"

        let alertView: UIAlertView = UIAlertView(title: title, message: message, delegate: self, cancelButtonTitle: "Cancel", otherButtonTitles: "Settings")
        alertView.show()
    }


    if CLLocationManager.authorizationStatus() == CLAuthorizationStatus.denied{

        var title: String

        title = "Location services are off"
        let message: String = "To post spots or find near by spots, you must turn on Location Services from Settings"

        let alertView: UIAlertView = UIAlertView(title: title, message: message, delegate: self, cancelButtonTitle: "Cancel", otherButtonTitles: "Settings")
        alertView.show()
    }

    if CLLocationManager.authorizationStatus() == CLAuthorizationStatus.notDetermined
    {
        startStandardUpdates()
    }
}

}

Call this functions in didfinishlaunchingwithoption

 func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

 let locationManager = locationManagerClass.sharedLocationManager()
        locationManager.startStandardUpdates()
}

3.Set camera in viewDidLoad of your class

 if UserDefaults.standard.object(forKey: "lat") != nil {
                let lat =  UserDefaults.standard.object(forKey: "lat") as! String
                let long = UserDefaults.standard.object(forKey: "long") as! String
                var userLoc = CLLocationCoordinate2D()
                userLoc.latitude = CDouble(lat)!
                userLoc.longitude = CDouble(long)!
                let span = MKCoordinateSpanMake(0.02, 0.02)
                let region = MKCoordinateRegion(center: userLoc, span: span)
                mapVw.setRegion(region, animated: true)
                mapVw.showsUserLocation = true

            }

Upvotes: 1

Related Questions