How I can center the map on user's location in swift? - ios

I'm writing an app and I have an embedded mapview to show user's his location. This is my code so far:
class YourCurrentLocation: UIViewController, CLLocationManagerDelegate {
#IBOutlet weak var mapView: MKMapView!
var locationManager = CLLocationManager()
let regionRadius: CLLocationDistance = 1000
func checkLocationAuthorizationStatus() {
if CLLocationManager.authorizationStatus() == .AuthorizedWhenInUse {
mapView.showsUserLocation = true
centerMapOnLocation(locationManager.location!, map: mapView, radius: regionRadius)
} else {
locationManager.requestAlwaysAuthorization() //requestWhenInUseAuthorization()
}
}
func centerMapOnLocation(location: CLLocation, map: MKMapView, radius: CLLocationDistance) {
let coordinateRegion = MKCoordinateRegionMakeWithDistance(location.coordinate,
radius * 2.0, radius * 2.0)
map.setRegion(coordinateRegion, animated: true)
}
override func viewDidLoad() {
super.viewDidLoad()
// mapView.delegate = self
if CLLocationManager.locationServicesEnabled()
{
//locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.requestAlwaysAuthorization()
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.startUpdatingLocation()
print("location enabled")
checkLocationAuthorizationStatus()
}
else
{
print("Location service disabled");
}
// Do any additional setup after loading the view.
}
}
I also added the two entries to my plist:
NSLocationAlwaysUsageDescription
NSLocationWhenInUseUsageDescription
and also in my xcode I have set to emulate the GPS data on london, UK.
When I run the app - I see the map, but london is not marked. What am I doing wrong?
Btw, I had to comment out this line:
//mapView.delegate = self
in viewDidLoad(), otherwise I had the error:
Cannot assign value of type YourCurrentLocation to type MKMapViewDelegate
and I'm not sure if that's a part of the problem here.
I want to achieve the effect when I display to the user map and a point marked on that map with his location. Can you help me with that?

The problem with your code is that you're trying to point the map to the user's location when the user gives location permission, you're not waiting for the CoreLocation to give you the actual user location.
You need to use the CLLocationManagerDelegate method locationManager(_:didUpdateLocations:) to be notified of when you get the user's actual location, and there you can set the map to point to the user's location.
class ViewController: UIViewController, CLLocationManagerDelegate {
#IBOutlet var mapView: MKMapView!
var locationManager: CLLocationManager?
override func viewDidLoad() {
super.viewDidLoad()
locationManager = CLLocationManager()
locationManager!.delegate = self
if CLLocationManager.authorizationStatus() == .AuthorizedWhenInUse {
locationManager!.startUpdatingLocation()
} else {
locationManager!.requestWhenInUseAuthorization()
}
}
func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
switch status {
case .NotDetermined:
print("NotDetermined")
case .Restricted:
print("Restricted")
case .Denied:
print("Denied")
case .AuthorizedAlways:
print("AuthorizedAlways")
case .AuthorizedWhenInUse:
print("AuthorizedWhenInUse")
locationManager!.startUpdatingLocation()
}
}
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location = locations.first!
let coordinateRegion = MKCoordinateRegionMakeWithDistance(location.coordinate, 500, 500)
mapView.setRegion(coordinateRegion, animated: true)
locationManager?.stopUpdatingLocation()
locationManager = nil
}
func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
print("Failed to initialize GPS: ", error.description)
}
}

Related

swift user location - update if move

So I have been able to get the users location via the following code.
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
if status != .authorizedWhenInUse {return}
print("test LOCATION BELOW")
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.startUpdatingLocation()
let locValue: CLLocationCoordinate2D = manager.location!.coordinate
print("UUID: \(String(describing: uuid)) locations = \(locValue.latitude) \(locValue.longitude)")
}
However I want to watch the users location and if they move update their location.
I am wondering how do I get this code to keep checking for the users location?
My
override func viewDidLoad(){
locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.requestWhenInUseAuthorization()
locationManager.requestAlwaysAuthorization()}
I get it popping up the request and I approve it but it does not run the code
Here is how you can get the location data. The code is similar to yours but with a bit of change and additions.
First check if you already have user's permission to get their location data.
func isLocationServicesEnabled() -> Bool {
if CLLocationManager.locationServicesEnabled() {
switch(CLLocationManager.authorizationStatus()) {
case .notDetermined, .restricted, .denied:
return false
case .authorizedAlways, .authorizedWhenInUse:
return true
#unknown default:
return false
}
}
return false
}
If this method returns false you can ask for authorization.
// Initialize manager in your viewDidLoad
override func viewDidLoad() {
super.viewDidLoad()
locationManager = CLLocationManager()
locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters
locationManager.delegate = self
// Do other stuff
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
// Check for auth
if isLocationServicesEnabled() {
locationManager.startUpdatingLocation()
} else {
locationManager.requestWhenInUseAuthorization()
}
// Do other stuff
}
Finally in your CLLocationManagerDelegate implementation get the coordinates.
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let location = locations.last?.coordinate else { return }
// Use location.latitude and location.longitude here
// If you don't want to receive any more location data then call
locationManager.stopUpdatingLocation()
}
First, you have to check that you have user's permission to get their location data
func checkLocationServicesAuthorization() -> Bool {
if CLLocationManager.locationServicesEnabled() {
switch CLLocationManager.authorizationStatus() {
case .notDetermined:
return false
case .restricted, .denied:
//code for open settings screen in user’s phone
return false
case .authorizedWhenInUse, .authorizedAlways:
return true
default:
return false
}
} else {
//code for open settings screen in user’s phone
}
return false
}
And
override func viewDidLoad() {
super.viewDidLoad()
locationManager = CLLocationManager()
locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters
locationManager.delegate = self
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
if checkLocationServicesAuthorization() {
locationManager.startUpdatingLocation()
} else {
locationManager.requestWhenInUseAuthorization()
}
}
You can use delegate method didUpdateLocations of CLLocationManagerDelegate and don't forgot to connect delegate yourLocationManager.delegate = self
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let userLocation:CLLocation = locations[0] as CLLocation
// Call stopUpdatingLocation() to stop listening for location updates, other wise this function will be called every time when user location changes.
// yourLocationManager.stopUpdatingLocation()
guard let locValue: CLLocationCoordinate2D = manager.location?.coordinate else { return }
let latitude = String.init(userLocation.coordinate.latitude)
let longitude = String.init(userLocation.coordinate.longitude)
print("\(latitude), \(longitude)")
}

Make user location visible on the map does not work

If I am running my code the rounded blue point isn't shown up on the map. user location visible on the map does not work. I can't find the problem for that. Anyone who can find the issue?
import UIKit
import MapKit
import CoreLocation
class GPSNewBin: UIViewController, CLLocationManagerDelegate {
#IBOutlet weak var mapView: MKMapView!
#IBOutlet weak var zurueckButton: UIButton!
var locationManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
// Ask for Authorisation from the User.
self.locationManager.requestAlwaysAuthorization()
// For use in foreground
self.locationManager.requestWhenInUseAuthorization()
if CLLocationManager.locationServicesEnabled() {
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
locationManager.startUpdatingLocation()
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
//guard let locValue: CLLocationCoordinate2D = manager.location?.coordinate else { return }
let locValue: CLLocationCoordinate2D = manager.location!.coordinate
print("locations = \(locValue.latitude) \(locValue.longitude)")
let userLocation = locations.last
let viewRegion = MKCoordinateRegion(center: (userLocation?.coordinate)!, latitudinalMeters: 600, longitudinalMeters: 600)
self.mapView.setRegion(viewRegion, animated: true)
}
}
Thanks a lot :)
You can enable user location from a storyboard:
OR
You can also enable it using code:
mapView.showsUserLocation = true
You must include following properties in Info.plist, without it your request for authorization will not work.
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>Message for AlwaysAndWhenInUseUsageDescription</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>Message for AlwaysUsageDescription</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Message for WhenInUseUsageDescription</string>
Use following method for requesting authorization in viewDidLoad, it also takes in account when location services is denied to the app.
func checkLocationAuthorization(authorizationStatus: CLAuthorizationStatus? = nil) {
switch (authorizationStatus ?? CLLocationManager.authorizationStatus()) {
case .authorizedAlways, .authorizedWhenInUse:
mapView.showsUserLocation = true
case .notDetermined:
locationManager.requestWhenInUseAuthorization()
default:
print("Location Servies: Denied / Restricted")
}
}
checkLocationAuthorization in viewDidLoad
override func viewDidLoad() {
super.viewDidLoad()
if CLLocationManager.locationServicesEnabled() {
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
locationManager.startUpdatingLocation()
}
self.checkLocationAuthorization()
}
You must also update the authorization status, when a CLLocationManagerDelegate.locationManager(_:didChangeAuthorization:) is occurred, you can re-use above method, like so:
extension GPSNewBin: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
self.checkLocationAuthorization(authorizationStatus: status)
}
}
When updating location in didUpdateLocations, use the updated user location sent in userLocation.coordinate, like so:
extension GPSNewBin: MKMapViewDelegate {
func mapView(_ mapView: MKMapView, didUpdate userLocation: MKUserLocation) {
let region = MKCoordinateRegion(center: userLocation.coordinate, latitudinalMeters: 600, longitudinalMeters: 600)
mapView.setRegion(region, animated: true)
}
}

Location manager didUpdateLocations not being called

For some reason didUpdateLocations is not being called, even when I set the delegate to the view controller. In info.plist I set the key Privacy - Location When In Use Usage Description to a description. So I'm not sure what I could be doing wrong?
import MapKit
import CoreLocation
class OptionsViewController: UIViewController, UITableViewDelegate, CLLocationManagerDelegate {
override func viewDidLoad() {
//Ask user for location
locationManager = CLLocationManager()
locationManager.requestWhenInUseAuthorization()
//Use users current location if no starting point set
if CLLocationManager.locationServicesEnabled() {
let locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.startUpdatingLocation()
}
}
override func viewDidAppear(_ animated: Bool) {
locationManager = CLLocationManager()
locationManager.requestWhenInUseAuthorization()
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error){
locationManager.stopUpdatingLocation()
print(error)
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
print("Did update location called?")
let locValue:CLLocationCoordinate2D = manager.location!.coordinate
print("locations = \(locValue.latitude) \(locValue.longitude)")
}
}
Problem is here:
override func viewDidAppear(_ animated: Bool) {
locationManager = CLLocationManager()
locationManager.requestWhenInUseAuthorization()
}
This method will be called after viewDidLoad, but you new created a locationManager later in viewDidAppear and not pointed its delegate to self. That's why the delegate(self)'s methods is not be called.
The improved but not the best way is:
class OptionsViewController: UIViewController, UITableViewDelegate, CLLocationManagerDelegate {
let locationManager = CLLocationManager()
override func viewDidLoad() {
//Ask user for location
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
//Use users current location if no starting point set
if CLLocationManager.locationServicesEnabled() {
if CLLocationManager.authorizationStatus() == CLAuthorizationStatus.authorizedWhenInUse
|| CLLocationManager.authorizationStatus() == CLAuthorizationStatus.authorizedAlways {
locationManager.startUpdatingLocation()
}
else{
locationManager.requestWhenInUseAuthorization()
}
}
else{
//Alert user to open location service, bra bra bra here...
}
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
//... nothing need to do for location here
}
public func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
if status == CLAuthorizationStatus.authorizedWhenInUse
|| status == CLAuthorizationStatus.authorizedAlways {
locationManager.startUpdatingLocation()
}
else{
//other procedures when location service is not permitted.
}
}
//......
}

How do I make "Center location on Map" work?

I am new to programing.
I have found the code below and it does everything but center location.(zoom in, map, blue dot all work.)
If I run in simulator, (city run) the blue dot just runs off the page.
import UIKit
import MapKit
import CoreLocation
import Foundation
class ViewController: UIViewController, CLLocationManagerDelegate {
#IBOutlet weak var map: MKMapView!
var locationManager: CLLocationManager?
override func viewDidLoad() {
super.viewDidLoad()
locationManager = CLLocationManager()
locationManager!.delegate = self
map.showsUserLocation = true
if CLLocationManager.authorizationStatus() == .authorizedWhenInUse {
locationManager!.startUpdatingLocation()
} else {
locationManager!.requestWhenInUseAuthorization()
}
}
private func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
switch status {
case .notDetermined:
print("NotDetermined")
case .restricted:
print("Restricted")
case .denied:
print("Denied")
case .authorizedAlways:
print("AuthorizedAlways")
case .authorizedWhenInUse:
print("AuthorizedWhenInUse")
locationManager!.startUpdatingLocation()
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location = locations.first!
let coordinateRegion = MKCoordinateRegionMakeWithDistance(location.coordinate, 500, 500)
map.setRegion(coordinateRegion, animated: true)
locationManager?.stopUpdatingLocation()
locationManager = nil
}
}
Delete your implementation of
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
Just get authorization, set map.showsUserLocation = true, and stand back.
Here is my Swift 3 code that works and is tested. It loads mapView, ask user's permission and zoom in into his location.
import UIKit
import MapKit
class ViewController: UIViewController, CLLocationManagerDelegate {
#IBOutlet weak var mapView: MKMapView!
let locationManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
locationManager.activityType = .automotiveNavigation
locationManager.distanceFilter = 10.0
mapView.showsUserLocation = true
mapView.mapType = .standard
self.mapView.delegate = self
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
locationManager.requestWhenInUseAuthorization()
locationManager.startUpdatingLocation()
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let userLocation:CLLocation = locations[0] as CLLocation
locationManager.stopUpdatingLocation()
let location = CLLocationCoordinate2D(latitude: userLocation.coordinate.latitude, longitude: userLocation.coordinate.longitude)
let span = MKCoordinateSpanMake(0.05, 0.05)
let region = MKCoordinateRegion (center: location,span: span)
mapView.setRegion(region, animated: true)
}
}

CLLocation Manager in Swift to get Location of User

I am trying to convert an old app in ObjC to Swift as a practice exercise and have ran in to some issues. The way I had it in the old app, it was establishing the CLLocation Manager and then I would use:
manager = [[CLLocationManager alloc]init];
manager.delegate = self;
manager.desiredAccuracy = kCLLocationAccuracyBest;
[manager startUpdatingLocation]
which would call automatically:
-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation{
}
and from there I could extract all the information I needed. But in swift, there is no autocompletion of this method and I cannot figure out how to reproduce it. The documentation says that
startUpdatingLocation()
will still be called by the delegate, but it isn't happening.
This is what I have so far:
import UIKit
import corelocation
class ViewController: UIViewController,CLLocationManagerDelegate{
#IBOutlet var gpsResult : UILabel
var manager:CLLocationManager!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
manager = CLLocationManager()
manager.delegate = self
manager.desiredAccuracy = kCLLocationAccuracyBest
manager.startUpdatingLocation()
}
func locationManager(manager:CLLocationManager, didUpdateLocations locations:AnyObject[]) {
println("locations = \(locations)")
gpsResult.text = "success"
}
}
Any help or pointers on where to look would be appreciated. Thanks.
EDIT: Updated from Suggestions, but still not working
EDIT2: Seems to be some bug not allowing the method to work properly in the ViewController
You are missing two things. First, you have to ask for permission using requestAlwaysAuthorization or requestWhenInUseAuthorization(). So your viewDidLoad() should be like this:
var locationManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestAlwaysAuthorization()
locationManager.startUpdatingLocation()
}
Second, edit your Info.plist as indicated here.
First add this two line in plist file
NSLocationWhenInUseUsageDescription
NSLocationAlwaysUsageDescription
Then this is class working complete implement this
import UIKit
import CoreLocation
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, CLLocationManagerDelegate {
var window: UIWindow?
var locationManager: CLLocationManager!
var seenError : Bool = false
var locationFixAchieved : Bool = false
var locationStatus : NSString = "Not Started"
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool {
initLocationManager();
return true
}
// Location Manager helper stuff
func initLocationManager() {
seenError = false
locationFixAchieved = false
locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.locationServicesEnabled
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestAlwaysAuthorization()
}
// Location Manager Delegate stuff
// If failed
func locationManager(manager: CLLocationManager!, didFailWithError error: NSError!) {
locationManager.stopUpdatingLocation()
if (error) {
if (seenError == false) {
seenError = true
print(error)
}
}
}
func locationManager(manager: CLLocationManager!, didUpdateLocations locations: AnyObject[]!) {
if (locationFixAchieved == false) {
locationFixAchieved = true
var locationArray = locations as NSArray
var locationObj = locationArray.lastObject as CLLocation
var coord = locationObj.coordinate
println(coord.latitude)
println(coord.longitude)
}
}
// authorization status
func locationManager(manager: CLLocationManager!,
didChangeAuthorizationStatus status: CLAuthorizationStatus) {
var shouldIAllow = false
switch status {
case CLAuthorizationStatus.Restricted:
locationStatus = "Restricted Access to location"
case CLAuthorizationStatus.Denied:
locationStatus = "User denied access to location"
case CLAuthorizationStatus.NotDetermined:
locationStatus = "Status not determined"
default:
locationStatus = "Allowed to location Access"
shouldIAllow = true
}
NSNotificationCenter.defaultCenter().postNotificationName("LabelHasbeenUpdated", object: nil)
if (shouldIAllow == true) {
NSLog("Location to Allowed")
// Start location services
locationManager.startUpdatingLocation()
} else {
NSLog("Denied access: \(locationStatus)")
}
}
}
I'm not sure why, but it seems like startUpdatingLocation isn't presenting the user prompt on the iOS 7 simulator, but when I enabled it manually it worked as expected if I used the newer form of the delegate method:
var manager:CLLocationManager!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
manager = CLLocationManager()
manager.delegate = self
manager.desiredAccuracy = kCLLocationAccuracyBest
manager.startUpdatingLocation()
}
func locationManager(manager:CLLocationManager, didUpdateLocations locations:[AnyObject]) { // Updated to current array syntax [AnyObject] rather than AnyObject[]
println("locations = \(locations)")
}
The format you're using has been deprecated since iOS 5 or 6, so apparently it's not supported at all by the swift bridging layers.
had the same issue. didUpdateLocations - was not working. Run your app. Go to the Settings page -> Privacy -> Location and turn off Location Services. didFailWithError will catch the error about absent Location Services. Then turn it on. Since that moment didUpdateLocations will catch locations.
Here is my very simple code that works:
first add Core Location framework in General/Linked Frameworks and Libraries
then add following into Info.plist:
<key>NSLocationWhenInUseUsageDescription</key>
<string>blablabla</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>blablabla</string>
this is my ViewController.swift file:
import UIKit
import CoreLocation
class ViewController: UIViewController, CLLocationManagerDelegate {
var locationManager:CLLocationManager!
override func viewDidLoad() {
super.viewDidLoad()
locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestAlwaysAuthorization()
locationManager.startUpdatingLocation()
}
func locationManager(manager:CLLocationManager, didUpdateLocations locations: [CLLocation]) {
print("locations = \(locations)")
}
}
For Swift 3
import UIKit
import CoreLocation
class ViewController: UIViewController,CLLocationManagerDelegate {
var locationManager:CLLocationManager!
override func viewDidLoad() {
super.viewDidLoad()
locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestAlwaysAuthorization()
locationManager.startUpdatingLocation()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func locationManager(_ manager:CLLocationManager, didUpdateLocations locations: [CLLocation]) {
print("locations = \(locations)")
}
}
I hope there are two ways.
var locationManager: CLLocationManager = CLLocationManager()
var initialLocation :CLLocation?
var updatedUserLocation :CLLocation?
override func viewDidLoad() {
super.viewDidLoad() {
//MapView Location
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
locationManager.requestWhenInUseAuthorization()
locationManager.startUpdatingLocation()
locationManager.startUpdatingHeading()
}
Implementing CLLocationManagerDelegate :
//CLLocationManager Delegate
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
// This only works when user location is updated.
gpsProviderStatusLabel.changeStatusToOn(gpsProviderStatusLabel)
}
func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
//Error indicates GPS permission restricted
gpsProviderStatusLabel.changeStatusToOff(gpsProviderStatusLabel)
//Initial Location
initialLocation = locations.first
//Getting Updated Location
updatedUserLocation = locations.last
}
Checking CLLocationDelegate Authorization:
func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
//This method does real time status monitoring.
switch status {
case .NotDetermined:
print(".NotDetermined")
break
case .AuthorizedAlways:
print(".AuthorizedAlways")
gpsProviderStatusLabel.changeStatusToOn(gpsProviderStatusLabel)
break
case .Denied:
print(".Denied")
gpsProviderStatusLabel.changeStatusToOff(gpsProviderStatusLabel)
break
case .AuthorizedWhenInUse:
print(".AuthorizedWhenInUse")
gpsProviderStatusLabel.changeStatusToOn(gpsProviderStatusLabel)
break
case .Restricted:
print(".Restricted")
break
default:
print("Unhandled authorization status")
break
}
}
Note: changeStatusToOn or changeStatusToOff is a UILabel Extenion method which makes the Label text On/Off with Green/Red Colors.
don't forget to add
NSLocationWhenInUseUsageDescription or
NSLocationAlwaysUsageDescription
in your configuration file (target/Info/custom iOS target properties
Add bellow 2 property in info.plist
NSLocationWhenInUseUsageDescription : Location information is used for fraud prevention
Privacy - Location Usage Description : Location information is used for fraud prevention
If you want to get the user location updated by default, without clicking 'Simulate location' everytime, go to
YourProject-->Build Phases-->Link Binary with libraries-->Add corelocation.framework
The location gets updated automatically/by default when you run the app in the simulator. Tested and works in Swift 2 !
This will ask for permission and track if given permission else quit with an alert. Stops tracking on back button press.
info.plist
<key>NSLocationAlwaysUsageDescription</key>
<string>Allow tracking while completing a survey</string>
Class:
import UIKit
import CoreLocation
class LocationViewController: BaseViewController, CLLocationManagerDelegate {
// MARK: Constants
private static let enableLocationServices = [
"title" : "Location",
"message" : "Enable location services",
"buttonTitle" : "OK"
]
// MARK: Private variables
private var manager: CLLocationManager?
// MARK: UIViewCOntroller methods
#IBAction func backButtonPressed(sender : UIButton) {
stopTracking()
detatchLocationManager()
dismissViewControllerAnimated(true, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
attachLocationManager()
}
// Mark: Location
func locationManager(manager: CLLocationManager,
didChangeAuthorizationStatus status: CLAuthorizationStatus)
{
if status == .AuthorizedAlways {
manager.startUpdatingLocation()
} else if status != .NotDetermined {
showEnableLocationServicesAlert()
}
}
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
for location in locations {
getDependencyService().getProject().appendLocationTrackingFile(location.timestamp, latitude: location.coordinate.latitude, longitude: location.coordinate.longitude)
}
}
// MARK: LocationViewController
private func attachLocationManager() {
manager = CLLocationManager()
manager?.delegate = self
manager?.desiredAccuracy = kCLLocationAccuracyBest
if CLLocationManager.authorizationStatus() != .AuthorizedAlways {
manager?.requestAlwaysAuthorization()
} else if CLLocationManager.locationServicesEnabled() {
startTracking()
}
}
private func detatchLocationManager() {
manager?.stopUpdatingLocation()
manager?.delegate = nil
manager = nil
}
private func startTracking() {
manager?.startUpdatingLocation()
}
private func stopTracking() {
manager?.stopUpdatingLocation()
}
private func showEnableLocationServicesAlert() {
getDependencyService().getUiHelper().showAlert(FrogFirstSurveyViewController.enableLocationServices, completion: {
self.dismissViewControllerAnimated(true, completion: nil)
})
}
}
Swift:
Add following in
import CoreLocation
class YourViewController: UIViewController
{
var locationManager:CLLocationManager!
}
//MARK:- Location Manager
extension YourViewController: CLLocationManagerDelegate {
func stratLocationManager()
{
locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
self.checkUsersLocationServicesAuthorization()
locationManager.startUpdatingLocation()
}
func checkUsersLocationServicesAuthorization(){
/// Check if user has authorized Total Plus to use Location Services
if CLLocationManager.locationServicesEnabled()
{
switch CLLocationManager.authorizationStatus()
{
case .notDetermined:
// Request when-in-use authorization initially
// This is the first and the ONLY time you will be able to ask the user for permission
self.locationManager.delegate = self
locationManager.requestWhenInUseAuthorization()
break
case .restricted, .denied:
// Disable location features
PrintLogs("Location Access Not Available")
break
case .authorizedWhenInUse, .authorizedAlways:
// Enable features that require location services here.
PrintLogs("Location Access Available")
break
}
}
}
func locationManager(_ manager:CLLocationManager, didUpdateLocations locations: [CLLocation]) {
print("locations = \(locations)")
}
}
Just call the init(vc : UIViewController).
import Foundation
import CoreLocation
import UIKit
class LocManager : NSObject{
var permission : ((Bool?)->())?
private var locationManager : CLLocationManager!
init(_ vc : UIViewController) {
super.init()
self.locationManager = CLLocationManager()
self.locationManager.delegate = vc as? CLLocationManagerDelegate
setUpLocationManagerDelegate()
}
}
extension LocManager : CLLocationManagerDelegate {
fileprivate func setUpLocationManagerDelegate(){
locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestAlwaysAuthorization()
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if let lat = locations.last?.coordinate.latitude, let long = locations.last?.coordinate.longitude{
print("\n\nThe current Lat/Long Is Here\n\n")
let coordinates = CLLocationCoordinate2D(latitude: lat, longitude: long)
}else{
print("Unable To Access Locaion")
}
}
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
switch status {
case .authorizedAlways,.authorizedWhenInUse:
print("Good to go and use location")
locationManager.startUpdatingLocation()
self.callPermisssionCompletion(val: true)
case .denied:
print("DENIED to go and use location")
self.callPermisssionCompletion(val: false)
case .restricted:
print("DENIED to go and use location")
self.callPermisssionCompletion(val: nil)
case .notDetermined:
print("DENIED to go and use location")
self.callPermisssionCompletion(val: nil)
default:
print("Unable to read location :\(status)")
}
}
fileprivate func callPermisssionCompletion(val : Bool?){
guard let comp = self.permission else {
print("\n\n Unable to locate completions \n\n")
return
}
if let val = val{
comp(val)
}
}
}

Resources