Reputation: 1189
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
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