Swift Not Reaching LocationManager Function - ios

I am trying to get my location in order to check how far I am from a certain longitude and latitude.
For some reason the program never reaches the LocationManager Function where I want to grab my coordinates.
I have set up the correct properties in info.plist and the app does ask for permission.
I added a function to check for errors and got:
didFailWithError Error Domain=kCLErrorDomain Code=0 "(null)"
import UIKit
import CoreLocation
import MapKit
class ViewController: UIViewController, CLLocationManagerDelegate {
var locationManager:CLLocationManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.delegate = self
locationManager.requestWhenInUseAuthorization()
locationManager.startUpdatingLocation()
print("location on")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
print("REACHED FUNCTION")
}
}

If you are using iOS 8.0 and later you need to ask for permission before starting to update location. You can use following code for that
if #available(iOS 8.0, *) {
locationManager.requestWhenInUseAuthorization()
}
Above code will go in viewDidLoad. And implement following delegate method
func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
switch status {
case .AuthorizedWhenInUse:
locationManager.startUpdatingLocation()
break
case .AuthorizedAlways:
locationManager.startUpdatingLocation()
break
default:
break
}
}

Related

get user location and updates

I am trying to get user location in my iPhone app. It has specified in info.plist needed permission (use location even if app is not offline). But still I do not see that my delegate is triggered at least once meaning I do not get even current location. Here is the code:
import UIKit
import CoreLocation
class ViewController: UIViewController, CLLocationManagerDelegate {
var locationManager = CLLocationManager();
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
locationManager.delegate = self
if (CLLocationManager.authorizationStatus() == CLAuthorizationStatus.notDetermined) {
self.locationManager.requestAlwaysAuthorization();
}
locationManager.distanceFilter = kCLDistanceFilterNone
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.startUpdatingLocation()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let userLocation:CLLocation = locations[0]
let long = userLocation.coordinate.longitude;
let lat = userLocation.coordinate.latitude;
print(lat)
}
func locationManager(manager: CLLocationManager!, didFailWithError error: NSError!)
{
locationManager.stopUpdatingLocation()
if ((error) != nil)
{
print(error)
}
}
Could somebody point me out possible problems?
Try to remove locationManager.stopUpdatingLocation() in locationManager(manager: CLLocationManager!, didFailWithError error: NSError!). It should work.

Google Maps iOS myLocation

I'm struggling with Google Maps' myLocation property, I always get nil, and can't figure out why. In my ViewDidLoad i set the following
map.myLocationEnabled = true
And in the function which gets called when the user wants to get his/her location, I run this:
print(map.myLocation)
I get that the first time it might got no location, but shouldn't I get a location after a while?
I thought the same thing as well but you actually need to get the user's location first through Apple's CLLocationManager api. import CoreLocation and make your VC adhere to CLLocationManagerDelegate and use the didUpdateLocations method to get the user's current location then reflect it unto GMaps.
import UIKit
import GoogleMaps
import CoreLocation
class MapVC: UIViewController
{
#IBOutlet weak var googleMap: GMSMapView!
var locationManager: CLLocationManager = CLLocationManager()
override func viewDidLoad()
{
super.viewDidLoad()
locationManager.delegate = self
locationManager.requestWhenInUseAuthorization()
}
override func didReceiveMemoryWarning()
{
super.didReceiveMemoryWarning()
}
}
extension MapVC: CLLocationManagerDelegate
{
func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus)
{
switch status
{
case .AuthorizedAlways:
print("Location AuthorizedAlways")
googleMap.myLocationEnabled = true
locationManager.startUpdatingLocation()
case .AuthorizedWhenInUse:
print("Location AuthorizedWhenInUse")
googleMap.myLocationEnabled = true
locationManager.startUpdatingLocation()
case .Denied:
print("Location Denied")
googleMap.myLocationEnabled = false
locationManager.stopUpdatingLocation()
case .NotDetermined:
print("Location NotDetermined")
googleMap.myLocationEnabled = false
locationManager.stopUpdatingLocation()
case .Restricted:
print("Location Restricted")
googleMap.myLocationEnabled = false
locationManager.stopUpdatingLocation()
}
}
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation])
{
if locations.count > 0
{
googleMap.camera = GMSCameraPosition.cameraWithTarget((locations.last?.coordinate)!, zoom: 10.0)
googleMap.settings.myLocationButton = true
}
}
}

CLLocationManager issue

I'm learning about user localization in swift. I'm trying to print localization on console (later I will use it for info on label, so I want to check if it works), but I have no idea why it prints nothing. Even if delete conversions to string, and leave just for printing anything, it still doesn't work. Please help.
Yes, I added NSLocationAlwaysUsageDescription and
NSLocationWhenInUseUsageDescription.
import UIKit
import CoreLocation
import MapKit
class ViewController: UIViewController, CLLocationManagerDelegate {
var locationManager = CLLocationManager()
var myPosition = CLLocationCoordinate2D()
override func viewDidLoad() {
super.viewDidLoad()
locationManager.delegate = self
locationManager.requestWhenInUseAuthorization()
locationManager.startUpdatingLocation()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func locationManager(manager: CLLocationManager, didUpdateToLocation newLocation: CLLocation, fromLocation oldLocation: CLLocation) {
print("Got location: \(newLocation.coordinate.latitude), \(newLocation.coordinate.longitude)")
myPosition = newLocation.coordinate
locationManager.stopUpdatingLocation()
}
}
didUpdateToLocation is an outdated method of the CLLocationManagerDelegate. It is available in 10.6 and earlier. Instead, use didUpdateLocations, which will return an array of all location objects in order of time recent. You then access the latest, newest location be grabbing the last object in the returned array.
So try this
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
var latestLocation: CLLocation = locations.last;
print("Got location: \(latestLocation.coordinate.latitude), \(latestLocation.coordinate.longitude)")
}
tell me how it goes.

unable to see locations: [CLLocation]

info.plist file:
<key>NSLocationWhenInUseUsageDescription</key>
<string>This project would like to know your location</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>location when app is in background</string>
As shown above, have added the key/value pairs for the info.plist
The problem i'm facing is that the first time i ran the app it prompted me for authorization, but, on subsequent runs the popup hasn't appeared.
second, I'm trying to print the locations from
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) using the print(location) but nothing is printed.
in the debug options i have set location as "city bicycle ride"
The code i'm using is as follows.
import UIKit
import MapKit
import CoreLocation
class ViewController: UIViewController, MKMapViewDelegate , CLLocationManagerDelegate {
#IBOutlet var map: MKMapView!
//use the locManager to get the users location
var locManager = CLLocationManager()
override func viewDidLoad() {
locManager.delegate = self
locManager.desiredAccuracy = kCLLocationAccuracyBest
locManager.requestWhenInUseAuthorization()
super.viewDidLoad()
}
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
print(locations)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
iOS will ask only once for location authorization. If the user denies, he will have to change this in the device settings manually. If he agrees, you will be able to obtain the location until he blocks it in the device settings.
So this code:
locManager.requestWhenInUseAuthorization()
will prompt a popup only 1 time. The problem is that you probably forget to call:
locManager.startUpdatingLocation()
You need to call this every time you want to start obtaining the location.
use this
override func viewDidLoad() {
super.viewDidLoad()
locationManager.delegate = self
locationManager.requestLocation()
locationManager.requestWhenInUseAuthorization()
locationManager.requestAlwaysAuthorization()
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.startUpdatingLocation()
}

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