I am using significant location change monitoring. When I run the code in the simulator and check Freeway option I get periodic location updates. I grab these updates and save them in NSUserDefaults and than update tableview every 10s, so I can see if I got any updates. If I run the app on a real device, I get zero updates. I kept the phone in my pocket and travelled over 80km, been in 2 cities. Zero updates. Not sure if I messed something up. I am attaching the code. The code is copy paste, feel free to test. Just make sure to use TableViewController in storyboard and set cell id to ID. What am I missing? I am testing on iphone 5.
info.plist:
edit: Found this in apple docs. Should my locationManager
be created differently?
When an app is relaunched because of a location update, the launch
options dictionary passed to your
application:willFinishLaunchingWithOptions: or
application:didFinishLaunchingWithOptions: method contains the
UIApplicationLaunchOptionsLocationKey key. The presence of that key
signals that new location data is waiting to be delivered to your app.
To obtain that data, you must create a new CLLocationManager object
and restart the location services that you had running prior to your
app’s termination. When you restart those services, the location
manager delivers all pending location updates to its delegate.
edit2:
Based on this, the location should be updated at least every 15min. Bug in my code confirmed.
If GPS-level accuracy isn’t critical for your app and you don’t need
continuous tracking, you can use the significant-change location
service. It’s crucial that you use the significant-change location
service correctly, because it wakes the system and your app at least
every 15 minutes, even if no location changes have occurred, and it
runs continuously until you stop it.
edit3: added this code to AppDelegate didFinishLaunchingWithOptions:
to see if app gets awaken. It does not get awaken-I see no 200 200 entry in table view. Something fishy is going on.
if let options = launchOptions {
print("options")
if (launchOptions![UIApplicationLaunchOptionsLocationKey] != nil){
locationManager.startUpdatingLocation()
self.lat.append(Double(200))
self.lon.append(Double(200))
self.times.append(NSDateFormatter.localizedStringFromDate(NSDate(), dateStyle: .NoStyle, timeStyle: .ShortStyle))
NSUserDefaults.standardUserDefaults().setObject(lat, forKey: "lat")
NSUserDefaults.standardUserDefaults().setObject(lon, forKey: "lon")
NSUserDefaults.standardUserDefaults().setObject(times, forKey: "time")
}
CODE:
//AppDelegate:
import UIKit
import CoreLocation
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, CLLocationManagerDelegate {
var lat:[CLLocationDegrees]!
var lon:[CLLocationDegrees]!
var times:[String]!
var distances: [String]!
var window: UIWindow?
var locationManager: CLLocationManager!
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
locationManager=CLLocationManager()
locationManager.delegate=self
locationManager.requestAlwaysAuthorization()
let isFirstLaunch = NSUserDefaults.standardUserDefaults().objectForKey("lat")
if isFirstLaunch == nil{
lat = [CLLocationDegrees]()
lon = [CLLocationDegrees]()
times = [String]()
NSUserDefaults.standardUserDefaults().setObject(lat, forKey: "lat")
NSUserDefaults.standardUserDefaults().setObject(lon, forKey: "lon")
NSUserDefaults.standardUserDefaults().setObject(times, forKey: "time")
}else{
lat = NSUserDefaults.standardUserDefaults().arrayForKey("lat") as! [CLLocationDegrees]
lon = NSUserDefaults.standardUserDefaults().arrayForKey("lon") as! [CLLocationDegrees]
times = NSUserDefaults.standardUserDefaults().objectForKey("time") as! [String]
// distances = NSUserDefaults.standardUserDefaults().objectForKey("distance") as! [String]
}
return true
}
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
print("location updated")
self.lat.append(locations[0].coordinate.latitude)
self.lon.append(locations[0].coordinate.longitude)
self.times.append(NSDateFormatter.localizedStringFromDate(NSDate(), dateStyle: .NoStyle, timeStyle: .ShortStyle))
NSUserDefaults.standardUserDefaults().setObject(lat, forKey: "lat")
NSUserDefaults.standardUserDefaults().setObject(lon, forKey: "lon")
NSUserDefaults.standardUserDefaults().setObject(times, forKey: "time")
print("Location: (locations[0].coordinate.latitude) (locations[0].coordinate.longitude)")
}
func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
print("did change AS")
switch status {
case .AuthorizedWhenInUse:
locationManager.startMonitoringSignificantLocationChanges()
case .AuthorizedAlways:
print("to always")
locationManager.startMonitoringSignificantLocationChanges()
if lat.count==0{
self.lat.append((locationManager.location?.coordinate.latitude)!)
self.lon.append((locationManager.location?.coordinate.longitude)!)
self.times.append(NSDateFormatter.localizedStringFromDate(NSDate(), dateStyle: .NoStyle, timeStyle: .ShortStyle))
NSUserDefaults.standardUserDefaults().setObject(lat, forKey: "lat")
NSUserDefaults.standardUserDefaults().setObject(lon, forKey: "lon")
NSUserDefaults.standardUserDefaults().setObject(times, forKey: "time")
}
// locationManager.startUpdatingLocation()
break
default:
locationManager.stopMonitoringSignificantLocationChanges()
break
}
}
}
// View Controller
import UIKit
class TableViewController: UITableViewController {
let appDel = UIApplication.sharedApplication().delegate as! AppDelegate
override func viewDidLoad() {
super.viewDidLoad()
NSTimer.scheduledTimerWithTimeInterval(10, target: self, selector: "updateTableView", userInfo: nil, repeats: true)
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return appDel.lon.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("ID", forIndexPath: indexPath)
cell.textLabel?.text = "(appDel.lat[indexPath.row]) (appDel.lon[indexPath.row]) (appDel.times[indexPath.row])"
cell.textLabel?.font = UIFont.systemFontOfSize(9)
return cell
}
func updateTableView(){
self.tableView.reloadData()
}
}
See Question&Answers more detail:
os