I've several questions to ask regarding the location updates in background in swift language.
Let me explain what I'm doing in the app. I'm developing an app which regularly monitors users location (as all of you do) and updates it to the server, so the users movement is tracked and saved for future reference by the user.
Questions
What is the difference between using startMonitoringSignificantLocationChanges Vs startUpdatingLocation?
1.1 If we use startUpdatingLocation does it impact on publishing the app to the App Store?
When the app is killed/suspended (Force closed by the user) it takes some time to restart the location manager from the AppDelegate which causes loss of location data for a period of time. Any possible solution to overcome this?
2.1 The difference of time for restarting is around 30 sec to nearly 1 min, which doesn't triggers the location update and hence the route is not perfect as shown in the image
Output of the App where due to restart the locations are not recieved and hence the route goes over the road.
Code for reference
import UIKit
import GoogleMaps
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, CLLocationManagerDelegate {
var window: UIWindow?
let DBName = "test"
var logFile: FileUtils?
var viewController:ViewController?
var count = 0
var appOpenCount = 0
let totalPath = GMSMutablePath()
var leaveCoordinates = 0
var previousLocation: CLLocationCoordinate2D = CLLocationCoordinate2D(latitude: 0, longitude: 0)
var locationManager: CLLocationManager?
var significatLocationManager : CLLocationManager?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
GMSServices.provideAPIKey("*********************")
logFile = FileUtils(fileName: "\(DBName).txt")
logFile!.appendFile("\n\nlaunchOptions : \(launchOptions)")
let defaults = NSUserDefaults.standardUserDefaults()
count = defaults.integerForKey("Enabled")
appOpenCount = defaults.integerForKey("appOpenCount")
if(UIApplication.sharedApplication().backgroundRefreshStatus == UIBackgroundRefreshStatus.Available){
logFile!.appendFile("\nYessss")
} else {
logFile!.appendFile("\nNooo")
}
appOpenCount += 1
defaults.setValue(appOpenCount, forKey: "appOpenCount")
defaults.synchronize()
if count == 0 {
count += 1
defaults.setValue(count, forKey: "Enabled")
defaults.synchronize()
Util.copyFile(count)
}
if let launchOpt = launchOptions{
if (launchOpt[UIApplicationLaunchOptionsLocationKey] != nil) {
logFile!.appendFile("\nExecuted on : significatLocationManager")
self.significatLocationManager = CLLocationManager()
self.significatLocationManager?.desiredAccuracy = kCLLocationAccuracyBest
self.significatLocationManager?.delegate = self
self.significatLocationManager?.requestAlwaysAuthorization()
if #available(iOS 9.0, *) {
self.significatLocationManager!.allowsBackgroundLocationUpdates = true
}
self.significatLocationManager?.startUpdatingLocation()
}else{
logFile!.appendFile("\nExecuted on : locationManager1")
self.locationManager = CLLocationManager()
self.locationManager?.desiredAccuracy = kCLLocationAccuracyBest
self.locationManager?.delegate = self
self.locationManager?.requestAlwaysAuthorization()
if #available(iOS 9.0, *) {
self.locationManager!.allowsBackgroundLocationUpdates = true
}
self.locationManager?.startUpdatingLocation()
}
} else {
logFile!.appendFile("\nExecuted on : locationManager2")
self.locationManager = CLLocationManager()
self.locationManager?.desiredAccuracy = kCLLocationAccuracyBest
self.locationManager?.delegate = self
self.locationManager?.requestAlwaysAuthorization()
if #available(iOS 9.0, *) {
self.locationManager!.allowsBackgroundLocationUpdates = true
}
self.locationManager?.startUpdatingLocation()
}
return true
}
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]){
let locationArray = locations as NSArray
let newLocation = locationArray.lastObject as! CLLocation
let coordinate = newLocation.coordinate
let tempCoor = CLLocationCoordinate2D(latitude: coordinate.latitude, longitude: coordinate.longitude)
let lat = tempCoor.latitude
let lon = tempCoor.longitude
insert(lat, lon: lon)
}
func applicationWillResignActive(application: UIApplication) {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}
func applicationDidEnterBackground(application: UIApplication) {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
if self.significatLocationManager != nil {
self.significatLocationManager?.startMonitoringSignificantLocationChanges()
}else{
self.locationManager?.startMonitoringSignificantLocationChanges()
}
logFile!.appendFile("\napplicationDidEnterBackground")
}
func applicationWillEnterForeground(application: UIApplication) {
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
}
func applicationDidBecomeActive(application: UIApplication) {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
func applicationWillTerminate(application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
func insert(lat: Double, lon: Double){
let locationInfo: LocationDetails = LocationDetails()
locationInfo.latitude = lat
locationInfo.longitude = lon
locationInfo.time = NSDate()
let db = "\(DBName)\(count).sqlite"
ModelManager.getInstance(db).addLocationData(locationInfo)
}
}