This question already has answers here:
CLLocation Manager in Swift to get Location of User
(13 answers)
Closed 6 years ago.
I'm trying to figure out how to get someones current location using SWIFT for a iOS app in XCODE.
I was following this tutorial here, but for some reason my code isn't working. I think it's because I am using a more updated Xcode versioning. For some reason my delegate has different parameters and I'm not sure why, but when I build my program it isn't even asking me if I want to allow location services at all.
Here is my code
override func viewDidLoad()
{
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
self.locationManager.requestWhenInUseAuthorization();
self.locationManager.startUpdatingLocation();
}
override func didReceiveMemoryWarning()
{
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// GPS STUFF
// UPDATE LOCATION
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
CLGeocoder().reverseGeocodeLocation(manager.location!) { (placemarks, ErrorType) -> Void in
if(ErrorType != nil)
{
print("Error: " + ErrorType!.localizedDescription);
return;
}
if(placemarks?.count > 0)
{
let pm = placemarks![0] ;
self.displayLocationInfo(pm);
}
}
}
// STOP UPDATING LOCATION
func displayLocationInfo(placemark: CLPlacemark)
{
self.locationManager.stopUpdatingLocation();
print(placemark.locality);
print(placemark.postalCode);
print(placemark.administrativeArea);
print(placemark.country);
}
Also, in info.plist I also added NSLocationWhenInUseUsageDescription.
Any advice would be great
In your Info.plist, add this:
or you can add like this in your Info.plist:
<key>NSLocationAlwaysUsageDescription</key>
<string>To get current location</string>
This will ask you to allow location services.
Hope this help you.
Related
My App relies on checking user location upon start.
On iOS 16, when the user enables the Developer Mode on Privacy Settings they can simulate any location on the device using a GPX file.
The device actually changes the location of the device and most apps that I use actually think my location is the one on the GPX file.
Is there a way to make sure the location is the actual user location or a simulated one ?
Is there a public API to check if Developer Mode is enabled ?
Is there a way to tell the location comes from the GPX file ?
Even if the Developer mode is turned off it takes restarting the device to pick up the actual location again , so not sure if there is a different and better solution to this.
Thank you.
Apple provides sourceInformation on each CLLocation object returned. Checking the isSimulatedBySoftware parameter will give a boolean response.
Core Location sets isSimulatedBySoftware to true if the system generated the location using on-device software simulation. You can simulate locations by loading GPX files using the Xcode debugger. The default value is false.
The code below is a full functioning example that will turn the screen red if a simulated location is detected. I have confirmed that toggling simulated locations on/off in Xcode will make the screen turn from green to red and back again.
import UIKit
import CoreLocation
class ViewController: UIViewController {
let locationManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
// setup location monitoring
locationManager.delegate = self
locationManager.requestWhenInUseAuthorization()
}
}
extension ViewController: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
// list of locations that are simulated
let simulatedLocations = locations.filter { $0.sourceInformation?.isSimulatedBySoftware == true }
view.backgroundColor = simulatedLocations.count > 0 ? .red : .green
}
func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
guard manager.authorizationStatus == .authorizedAlways || manager.authorizationStatus == .authorizedWhenInUse else { return }
locationManager.startUpdatingLocation()
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print(error.localizedDescription)
}
}
SITUATION:
I followed the following tutorial:
https://www.raywenderlich.com/95014/geofencing-ios-swift
PROBLEM:
The following functions never get triggered:
AppDelegate.swift
func locationManager(manager: CLLocationManager, didEnterRegion region: CLRegion) {
if region is CLCircularRegion {
handleRegionEvent(region)
}
}
func locationManager(manager: CLLocationManager, didExitRegion region: CLRegion) {
if region is CLCircularRegion {
handleRegionEvent(region)
}
}
func handleRegionEvent(region: CLRegion!) {
print("Geofence triggered!")
// Show an alert if application is active
if UIApplication.sharedApplication().applicationState == .Active {
if let message = notefromRegionIdentifier(region.identifier) {
if let viewController = window?.rootViewController {
showSimpleAlertWithTitle("Congratulations", message: "You just found: " + message , viewController: viewController)
}
}
} else {
// Otherwise present a local notification
let notification = UILocalNotification()
notification.alertBody = "You just found: " + notefromRegionIdentifier(region.identifier)!
notification.soundName = "Default";
UIApplication.sharedApplication().presentLocalNotificationNow(notification)
}
}
QUESTION:
The tutorial was written for iOS 8. I am currently on iOS 9.3. What caused this issue in your opinion and how do I fix it ?
You didn't show the code that you use to set up CL - which is probably where your problem lies.
Did you edit info.plist?
Are you requesting permission?
Did you call one of the start functions on the CL manager?
Make sure of two things :-
1.) You have added These to your viewDidLoad() :-
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.distanceFilter = kCLDistanceFilterNone
locationManager.requestWhenInUseAuthorization()
locationManager.startMonitoringSignificantLocationChanges()
locationManager.startUpdatingLocation()
Another alternative to requestWhenInUseAuthorization() and startUpdatingLocation() initialisation in specific to Swift 2.2, since in Swift 2.2 the string literals for selectors is deprecated, and instead there this new operator #selector that you need to be using. :-
you can also use :-
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.distanceFilter = kCLDistanceFilterNone
locationManager.startMonitoringSignificantLocationChanges()
if locationManager.respondsToSelector(#selector(locationManager.requestWhenInUseAuthorization)) {
locationManager.requestWhenInUseAuthorization()
}
else {
locationManager.startUpdatingLocation()
}
//Prefer the FIRST ONE.
2.) You have updated your info.plist with :-
NSLocationAlwaysUsageDescription : String :-> I need location.
NSLocationWhenInUseUsageDescription: String :-> I need location.
privacy - location usage description: String :-> I need location.
Edit I need location according to the app's need
PS :- If it still not calls your locationManager functions
Simulator :- look for location settings of your app in your simulator settings.
Device: - Go in settings > Privacy > Location services > Your app > Always.
you also might find this explanation useful : - https://stackoverflow.com/a/26090094/6297658
initialize your location manager in app delegate on did finish launching
my viewController looks like following
import CoreLocation
class MyViewController: UIViewController {
let locationManager = CLLocationManager()
override func viewDidAppear(animated: Bool) {
if #available(iOS 8.0, *) {
self.locationManager.requestWhenInUseAuthorization()
} else {
// Fallback on earlier versions
}
if (CLLocationManager.locationServicesEnabled()) {
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.startUpdatingLocation()
let lon = locationManager.location!.coordinate.longitude
let lat = locationManager.location!.coordinate.latitude
print("lat = \(lat) and long = \(lon)")
}
}
}
// MARK: - CLLocationManagerDelegate
extension MyViewController : CLLocationManagerDelegate {
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
self.locationManager.stopUpdatingLocation()
}
func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
print("\(error.localizedDescription)")
}
}
When I execute my program, it prompts a message like
Allow application to access your location while you use the app?
But the Don't Allow and Allow buttons are disabled.
Can someone guide me on where I am going wrong and what I should be doing.
I can manually allow my application to access location services by going to settings. But I would like to know why the buttons are disabled and what should I do to enable it.
note: I have added NSLocationWhenInUseUsageDescription to my info.plist file.
Thanks.
Dt: 29Oct2015
EDIT:
Uninstalled the app and installed again and tried. Now I am able to access the buttons.
Also, I noticed that sometimes the screen goes unresponsive i.e., screen cannot take any input from user. I noticed it today with a textbox. I am not able to get the cursor to the text box.
Is it something to do with IOS update? is anyone else experiencing this type of weird behaviour. Is there any workaround for the same?
Any help is highly appreciated.
Thanks.
I've been attempting to retrieve a iPhone's latitude and longitude for purposes of passing to an external function in order to geotag something. However, I've been rather unsuccessful. Here is the code I'm working with right now.
let locationManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.locationManager.requestAlwaysAuthorization()
self.locationManager.requestWhenInUseAuthorization()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func findMyLocation (sender:AnyObject)
{
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.startUpdatingLocation()
}
func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!)
{
CLGeocoder().reverseGeocodeLocation(manager.location, completionHandler: {(placemarks, error)->Void in
if error == nil
{
println("Reverse geocoder failed with error " + error.localizedDescription)
return
}
if placemarks.count > 0
{
let pm = placemarks[0] as CLPlacemark
self.displayLocationInfo(pm)
}
else
{
println("Problem with the data received from geocoder")
}
})
}
func displayLocationInfo(placemark: CLPlacemark) {
//stop updating location to save battery life
locationManager.stopUpdatingLocation()
if (placemark.postalCode != nil)
{
println(placemark.postalCode)
println("just tried to print placemark's postal code")
}
//println(placemark.locality ? placemark.locality : "")
//println(placemark.postalCode ? placemark.postalCode : "")
//println(placemark.administrativeArea ? placemark.administrativeArea : "")
//println(placemark.country ? placemark.country : "")
}
func locationManager(manager: CLLocationManager!, didFailWithError error: NSError!)
{
println("Error while updating location " + error.localizedDescription)
}
As of now, I get pretty much nothing when I run the program. I have a little button that says "Find Me", and upon clicking, nothing pops up in the output box. I have the iOS Simulator's Debug location set to "Apple", and I've previously tried always enabling location services in settings on the simulator when trying to run the program (although currently it's not showing my app and the option to do so).
I really just want to get a double value for latitude and longitude, and if there's a simple something that'd be great.
You should only request one type of authorization. Pick the one that makes the most sense for the user experience of your app.
You are probably missing your purpose string, which is now required to activate location services. Add one of the following keys to your Info.plist:
NSLocationAlwaysUsageDescription - if requesting Always permission
NSLocationWhenInUseUsageDescription - if requesting WhenInUse permission
The value of the key should be a string that explains why you want location permissions.
I've recently gotten into mobile programming. The code below is finicky; sometimes it works and sometimes it doesn't. I've tried suggestions I've found on here like restarting location services on the virtual iphone. It is not a info.plist issue: I have NSLocationWhenInUseUsageDescription set, and when I'm debugging I can see it has WhenInUse authorization. When I debug I get to the println statement in didFailWithError and it reads "The operation couldn’t be completed. (kCLErrorDomain error 0.)". I've put the code behind a button to try it out. Is the reliability of this a known issue? If I load the app onto a device will it go away? Any thoughts appreciated. Thanks.
EDIT
This is in ViewController.swift in a single view template application.
let manager = CLLocationManager()
#IBAction func getMyLocation (sender : AnyObject){
manager.delegate = self
manager.desiredAccuracy = kCLLocationAccuracyBest
let status = CLLocationManager.authorizationStatus()
if status == CLAuthorizationStatus.NotDetermined
{
manager.requestWhenInUseAuthorization()
}
manager.startUpdatingLocation()
}
func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
println("locations = \(locations)")
manager.stopUpdatingLocation()
}
func locationManager(manager: CLLocationManager!, didFailWithError error: NSError!){
println(error)
manager.stopUpdatingLocation()
}
I download the the app developer kit from Apple, and when I run the app with this script on my iphone the location is reliably retrieved. Looks like it's just an iOS simulator issue.