location manager not updating in swift ios10 - ios

I am new to swift and am trying to get a basic program that display the longitude and latitutde.
import UIKit
import CoreLocation
class ViewController: UIViewController, CLLocationManagerDelegate {
#IBOutlet weak var latLabel: UILabel!
#IBOutlet weak var longLabel: UILabel!
#IBOutlet weak var addLabel: UILabel!
var lm = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
lm = CLLocationManager()
}
#IBAction func getCurrentLocation(_ sender: AnyObject) {
lm.delegate = self
lm.desiredAccuracy = kCLLocationAccuracyBest
lm.startUpdatingLocation()
print("loc")
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print ("error")
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
print ("location")
let length = locations.count
let curLoc = locations[length-0]
latLabel.text = String(curLoc.coordinate.latitude)
print ("loccation")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}

You are missing two things.
you have to ask for permission using requestAlwaysAuthorization or requestWhenInUseAuthorization().
So when you are allocating your location manager in viewdidlod, Do like this
locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestAlwaysAuthorization()
You need to add information as #Anbu.Karthik has suggested in his answer.
Use NSLocationAlwaysUsageDescription for apps that want to use the
device's location even when the app is not open and being used.
Use NSLocationWhenInUseUsageDescription for apps that want to use the
device's location only when the app is open and in use.

check once are you added the following information your plist
Location :
Key : Privacy - Location Always Usage Description
Value : $(PRODUCT_NAME) location use
Key : Privacy - Location When In Use Usage Description
Value : $(PRODUCT_NAME) location use
for more information see this

One other issue that I found caused the location update callback not to be called, with no obvious error message given is that it must not be a private function (which is obvious once you finally notice it, of course...). I realise the OP's one is not but this is a common place to end up if you are having issues, so it may help someone.
So the following will cause the function not to be called without giving any obvious error indication like crashing the app etc:
private func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
print ("location")
let length = locations.count
let curLoc = locations[length-0]
latLabel.text = String(curLoc.coordinate.latitude)
print ("loccation")
}
Removing the 'private' keyword, as in the OP's code, will allow it to be called.

Related

How to add current timestamp in camera in ios app

Something like this I want to add current timestamp when recording is done in the video and save into camera roll.
**Note **: I have successfully added current location and timestamp in AVVideoPreviewLayer but it is static after exporting video is show static time does not show running timestamp
Try creating a layer of previewLayer: UIView with the components you want to have on camera.
Add this layer to currently running session of AVCaptureVideoPreviewLayer.
This link might help you to achieve your problem
Adding objects over camera view in app (Swift 3) not under camera view?
I tried something out. I guess you want to get latitude, longitude and the timestamp.
You find an example for latitude and longitude below.
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.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func showLocation(_ sender: Any) {
locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestAlwaysAuthorization()
if(CLLocationManager.locationServicesEnabled()){
locationManager.startUpdatingLocation()
}
locationManager.stopUpdatingLocation()
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let userLocation:CLLocation = locations[0] as CLLocation
print("user latitude = \(userLocation.coordinate.latitude)")
print("user longitude = \(userLocation.coordinate.longitude)")
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error)
{
print("Error \(error)")
}
}
To get the current time you can use something like this:
let date = NSDate()
print(date)
The result for both in console should look something like this:
2017-12-17 21:45:39 +0000
user latitude = 37.3322499
user longitude = -122.056264
(The time looks like this in my example because im from EU but you can convert it to what you want)
You can add this to a separate view and bring it to front with
view.bringSubview(toFront: YourView)
I hope this is helpful!

Magnetic Heading sample code for iOS

Can anyone provide me with a short snippet that will return me the magnetic heading of the iPhone?
I do not want Objective-C please. I need it in Swift.
I have written these lines so far but it does not return me any value:
let locManager = CLLocationManager()
locManager.desiredAccuracy = kCLLocationAccuracyBest
locManager.requestWhenInUseAuthorization()
locManager.startUpdatingLocation()
locManager.startUpdatingHeading()
locManager.headingOrientation = .portrait
locManager.headingFilter = kCLHeadingFilterNone
print(locManager.heading?.trueHeading.binade as Any)
Thanks!
You didn't set the delegate for the location manager. iOS does not update your location right away. Rather, it will call a function provided by your delegate when it has a location / heading update. The reason behind this setup is efficiency. Instead of 10 apps having 10 different location managers competing for time on the GPS hardware, these 10 location managers will request to be notified when the GPS has an update.
Try this:
class ViewController: UIViewController, CLLocationManagerDelegate {
#IBOutlet weak var label: UILabel!
var locManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
locManager.desiredAccuracy = kCLLocationAccuracyBest
locManager.requestWhenInUseAuthorization()
locManager.headingOrientation = .portrait
locManager.headingFilter = kCLHeadingFilterNone
locManager.delegate = self // you forgot to set the delegate
locManager.startUpdatingLocation()
locManager.startUpdatingHeading()
}
// MARK: -
// MARK: CLLocationManagerDelegate
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print("Location Manager failed: \(error)")
}
// Heading readings tend to be widely inaccurate until the system has calibrated itself
// Return true here allows iOS to show a calibration view when iOS wants to improve itself
func locationManagerShouldDisplayHeadingCalibration(_ manager: CLLocationManager) -> Bool {
return true
}
// This function will be called whenever your heading is updated. Since you asked for best
// accuracy, this function will be called a lot of times. Better make it very efficient
func locationManager(_ manager: CLLocationManager, didUpdateHeading newHeading: CLHeading) {
label.text = "\(newHeading.magneticHeading)"
}
}

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()
}

Value of distance between 2 CLLocation points does not appear on label text

I am trying to calculate the distance from the starting position I am (when i first start the app) to the current position and present it on a label (meters.text) but nothing appears on it..
Here is my code:
import UIKit
import CoreLocation
class CorrectViewController: UIViewController,CLLocationManagerDelegate {
#IBOutlet weak var meters: UILabel!
var wr: Int = 0
var distance = CLLocationDistance()
let locationManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
self.locationManager.delegate = self
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
self.locationManager.requestWhenInUseAuthorization() //starts when i use the app
self.locationManager.distanceFilter = kCLHeadingFilterNone
self.locationManager.startUpdatingLocation()
}
//locatioManager delegate method
func locationManager(manager: CLLocationManager, didUpdateToLocation newLocation: CLLocation, fromLocation oldLocation: CLLocation) {
let currentLocation: CLLocation = newLocation
let startLocation: CLLocation = oldLocation
distance = startLocation.distanceFromLocation(currentLocation)
let tripString = NSString(format: "%.2f", distance)
meters.text = ("\(tripString)")
}
func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
meters.text = ("error!")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
Any help is appreciated:)
It appears that the location update delegate method is inside the viewDidLoad function and hence defines a local function rather than implementing the delegate method.
Move the following method out of the viewDidLoad scope:
locationManager(manager: CLLocationManager, didUpdateToLocation newLocation: CLLocation, fromLocation oldLocation: CLLocation)
In addition you are not requesting permission to use the users location. Make sure to do that and add the necessary string to your info plist.
Also: oldLocation will always be the previous location (not your initial one).
Alright, after a lot of searching and "trial and error" I found the solution here.
Instead of using the method didUpdateToLocation the method didUpdateLocations should be used. Moreover, it is really important to put NSLocationAlwaysUsageDescription or NSLocationWhenInUseUsageDescription keys in the .plist file (value may be an additional message that will be presented in location alert). These keys are required in iOS 8.

CLLocationManagerDelegate methods not being called in Swift code

I'm trying to create a simple app that finds out the region someone is in, but I'm stuck because none of the CLLocationManagerDelegate methods are called when the app runs and finds locations.
In case it's relevant I'm also not seeing the dialog asking that I give the app permission to use location.
Here's what I have so far -
import UIKit
import CoreLocation
class ViewController: UIViewController, CLLocationManagerDelegate {
#IBOutlet weak var locationLabel : UILabel!
var locationManager = CLLocationManager()
let geocoder = CLGeocoder ()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.startUpdatingLocation()
}
override func viewDidDisappear(animated: Bool) {
locationManager.stopUpdatingLocation()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
geocoder.reverseGeocodeLocation(locations.last as CLLocation, completionHandler: {(placemark, error) in
if (error != nil) {
println("Error")
} else {
let pm = placemark.first as CLPlacemark
println(pm)
}
})
}
func locationManager(manager: CLLocationManager!, didFailWithError error: NSError!) {
println("Epic Fail")
}
}
I've put in breakpoints so I know the code is never called. I have gone in and manually turned on location services for the app while it's been running too.
try calling
func locationManager(manager: CLLocationManager!, didUpdateToLocation newLocation: CLLocation!, fromLocation oldLocation: CLLocation!)
instead of the delegate call you are making now...
I had problems with:
func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!)
aswell. But using the above delegate call fixed my issue.
Edit (didn't read the question properly...)
You never ask for permission, which is why you don't get a popup. Call the following:
locationManager.requestWhenInUseAuthorization()
This is quite an important step, and your app won't work if you haven't asked the user for authorization of your app
It is also important that you add NSLocationWhenInUseUsageDescription to your .plist file if running iOS8.
Screenshot:
The following answer question and answer gave me the solution I needed.
CLLocationManager authorization issue iOS 8
Ultimately if you're running on iOS then you must add the key
NSLocationAlwaysUsageDescription (when requesting location data to be always available)
OR
NSLocationWhenInUseUsageDescription (when requesting to use location data only when your app is running)
If you do not do this the location services access will be denied by default for your app and the user will not be prompted to allow it.
private let loctionManager = CLLocationManager() // Here
class YourViewController: ViewController {
loctionManager.delegate = self
loctionManager.requestWhenInUseAuthorization()
}
extension YourViewController: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
if (status == .authorizedWhenInUse) {
// do something
}
}
}
.plist
Property List
Key: Privacy - Location When In Use Usage Description
Type: String
Value: Use to add a location to your rap.
OR
Source code
<key>NSLocationWhenInUseUsageDescription</key>
<string>Use to add a location to your rap.</string>
If you tried all other answers and still having issues, just make sure CLLocationManager.init() and startUpdatingLocation are called on the same thread, preferably main thread.
I personally had a project and took me a while to figure out!

Resources