How to disable location service programmatically in iOS? - ios

I have the following:
class AppDelegate: UIResponder, UIApplicationDelegate, CLLocationManagerDelegate {
...
let locationManager = CLLocationManager()
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
if CLLocationManager.locationServicesEnabled() {
locationManager.delegate = self
locationManager.allowsBackgroundLocationUpdates = true
locationManager.distanceFilter = 3000.0
locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers
locationManager.requestAlwaysAuthorization()
locationManager.startUpdatingLocation()
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
print("my location: \(locations.first?.coordinate)")
locationManager.stopUpdatingLocation()
locationManager.delegate = nil
}
}
But even when the app is turned off i see the location service icon in status bar:
I wonder if there is a way to disable it programmatically. Thanks in advance!

In your plist file, you must make sure the location row is Privacy - LocationWhenInUseUsageDescription not Privacy - LocationAlwaysUsageDescription

Related

Can not called locationManager(_::didUpdateLocations:)

I tried get the coordinates when user launched app.
I setted up the locationManager code in a independent file:
UserLocation.swift:
import Foundation
import CoreLocation
class UserLocation: NSObject, CLLocationManagerDelegate {
var userCurrentLocation: CLLocationCoordinate2D?
let locationManager = CLLocationManager()
func locationSetup() {
locationManager.requestWhenInUseAuthorization()
if CLLocationManager.authorizationStatus() != CLAuthorizationStatus.authorizedWhenInUse {
print("authorization error")
return
}
locationManager.distanceFilter = 300
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.delegate = self
locationManager.startUpdatingLocation()
print("startUpdatingLocation")
if CLLocationManager.locationServicesEnabled() {
print("locationServicesEnabled")
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
print("locationManager getting start")
if let location = locations.last {
self.userCurrentLocation = CLLocationCoordinate2D(latitude: location.coordinate.latitude, longitude: location.coordinate.longitude)
print("print location in locationManager: \(String(describing: userCurrentLocation?.latitude))")
locationManager.stopUpdatingLocation()
}
}
func locationManager(_ manager: CLLocationManager, didFinishDeferredUpdatesWithError error: Error?) {
print(error?.localizedDescription as Any)
return
}
}
then, I call the func in the AppDelegate.swift's application(_::didFinishLaunchingWithOptions:) like this:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let getUserLocation = UserLocation()
getUserLocation.locationSetup()
}
but , the only calls locationSetup() function successfully , never called the related function locationManager(_::didUpdateLocations:). the print("locationManager getting start") I putted the first line in the locationManager(_::didUpdateLocations:), never printed out
BTW, in the info.plist , I already set Privacy - Location When In Use Usage Description .
can anyone help me out ?
Your getUserLocation is a local variable. It goes out of existence 1 millisecond after you create it. So it never has time to do anything (e.g. location updating). Promote it to an instance variable so that it lives longer:
var getUserLocation : UserLocation?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
self.getUserLocation = UserLocation()
self.getUserLocation?.locationSetup()
return true
}
(Also please use better variable names. An object reference should not begin with a verb.)
Please cross-check simulator location: Simulator -> Debug -> Locations that shouldn't be None in your case...
Hope this will help you... Thanks :)

iOS - CLLocationManager didUpdateLocations not being called in background

I want my iOS app to update it's location when closed and make post requests but location manager didUpdateLocations doesn't get called from the background despite it working fine in normal app use. Below is my SendLocation class. Calling determineCurrentLocation() get it going.
My problem is that if I call determineCurrentLocation() from another class while the app is running - it works perfectly. But when I call it from the App Delegate didUpdateLocations never gets called.
class SendLocation: NSObject, CLLocationManagerDelegate{
var locationManager:CLLocationManager = CLLocationManager()
struct LocationStruct{
var latitude:CLLocationDegrees?, longitude:CLLocationDegrees?
}
var locationStruct = LocationStruct()
var userLocation: CLLocation? = nil
func sendLocationPost(){
// This function makes the POST
}
func determineCurrentLocation(){
locationManager.delegate = self
locationManager.allowsBackgroundLocationUpdates=true
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestAlwaysAuthorization()
if CLLocationManager.locationServicesEnabled(){
DispatchQueue.main.async {
print("test1") // This prints fine from background
self.locationManager.startUpdatingLocation()
}
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]){
print("test2") // This never gets printed from backgrounf
locationManager.stopUpdatingLocation()
userLocation = locations[0] as CLLocation
locationStruct.latitude=userLocation?.coordinate.latitude
locationStruct.longitude=userLocation?.coordinate.longitude
sendLocationPost()
}
Below are the two functions I edited in my App Delegate:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
UIApplication.shared.setMinimumBackgroundFetchInterval(UIApplicationBackgroundFetchIntervalMinimum)
return true
}
func applicationDidEnterBackground(_ application: UIApplication) {
let sendLocation = SendLocation()
sendLocation.determineCurrentLocation()
}
My Info.plist has been changed to be correct, as far as I know.
Here is a picture of my Background Modes
And my privacy settings
Just in case I'm missing something there.
If anyone has any ideas what I've done wrong then I'd be very appreciative of some help.

AppDelegate Extension not getting called

I am trying to get the users location immediately on start up, and to do this I have implemented a global variable userLocation that will get updated in the AppDelegate's didFinishLaunchingWithOptions function. I have implemented the location manager like so:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
var locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.requestWhenInUseAuthorization()
if CLLocationManager.locationServicesEnabled(){
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestLocation()
}
return true
}
and the extension:
extension AppDelegate: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
usersLocation = locations.last!
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print(error)
}
}
The userLocation never gets updated, and I placed a break point on the userLocation = locations.last! line and it never reaches that.
Thanks for any advice
I think you should keep the locationManager variable too.
var locationManager: CLLocationManager!
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.requestWhenInUseAuthorization()
if CLLocationManager.locationServicesEnabled(){
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestLocation()
}
return true
}

Location service randomly not working

I have a strange issue with the apple location service.
First of all the code that I'm using to get user location:
import CoreLocation
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate,UISplitViewControllerDelegate,CLLocationManagerDelegate {
//Core location
let locationManager = CLLocationManager()
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
//Core Location
// Ask for Authorisation from the User.
self.locationManager.requestAlwaysAuthorization()
//Clore Location
// For use in foreground
self.locationManager.requestWhenInUseAuthorization()
if CLLocationManager.locationServicesEnabled() {
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
locationManager.startUpdatingLocation()
}
return true
}
And my info.plist file:
Randomly, when I launch the simulator, my app don't get the location. Normally I change the simulator device, from iphone 6s to iphone 6 and it fix the issue. But today I've changed from a city to another and I'm having this issue in my device all the time. I cannot get the location. Anybody have an idea what can it be? Is this a bug from apple? Is there a solution?
Thanks!
EDIT: added didUpdateLocations but the whole problem is this method is never being called
//Core Location Delegate Methods
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]){
//Set coordinates to global var
let coordinates : CLLocationCoordinate2D = manager.location!.coordinate
locValue = coordinates
setCoordinatesDetails(coordinates)
if(self.hasBeenLaunched == false){
self.hasBeenLaunched = true
loadCitySlugArray()
}
}

iOS background mode location update - manager doesn't update in background mode

I just followed http://www.raywenderlich.com/92428/background-modes-ios-swift-tutorial location update part.
But manager doesn't print location info in background mode.
Then manager print logs to Xcode's console when app enter foreground.
Is this code right?
import UIKit
import CoreLocation
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, CLLocationManagerDelegate {
var window: UIWindow?
var manager = CLLocationManager()
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
manager.desiredAccuracy = kCLLocationAccuracyBest
manager.delegate = self
manager.requestAlwaysAuthorization()
manager.startUpdatingLocation()
return true
}
func locationManager(manager: CLLocationManager, didUpdateToLocation newLocation: CLLocation, fromLocation oldLocation: CLLocation) {
if UIApplication.sharedApplication().applicationState != .Active {
NSLog("App is backgrounded. New location is %#", newLocation)
}
}
.....
}
I got answer for myself.
If your app running on iOS 9.0 or above and want to run your location service app on background,
you have to allowsBackgroundLocationUpdates variable set to true.
so here is my code.
import UIKit
import CoreLocation
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, CLLocationManagerDelegate {
var window: UIWindow?
var manager = CLLocationManager()
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
manager.desiredAccuracy = kCLLocationAccuracyBest
manager.delegate = self
manager.requestAlwaysAuthorization()
manager.startUpdatingLocation()
if #available(iOS 9.0, *){
manager.allowsBackgroundLocationUpdates = true
}
return true
}
func locationManager(manager: CLLocationManager, didUpdateToLocation newLocation: CLLocation, fromLocation oldLocation: CLLocation) {
if UIApplication.sharedApplication().applicationState != .Active {
NSLog("App is backgrounded. New location is %#", newLocation)
}
}
.....
}

Resources