CLLocationManager stops updating at sea

Hi, I am iOS developer making an app to track my ocean swims. The idea sounds a bit strange but from my understanding should work as a charm, all I am trying to do is to make iPhone log my current GPS coordinates to the file in background while I swim in the ocean.


Here is what I did:


1. iPhone in a protected case is being attached to my body at about 5 cm above sea level. Runs iOS 8.3(12F70) or 8.2(12D508).

2. App is written in Swift, uses background mode (delegate call didUpdateLocations uses beginBackgroundUpdateTask() / endBackgroundTask()

3. Tested on iPhone 6 and iPhone 5 and have the same result.

4. Same app tested when iPhone is descended into the bucket with a water (~ about 20 cm under water) - works complately fine( at least for first several minutes).

5. App logs retrived coordinates to a file and it changes file every ~100 reads to avoid delays related to open/read/write operations on files.

6. Same app tested on the ground while walking, cycling or driving a car - works just fine.


However when I did a couple of ocean swims with it (using 2 iPhones for testing purposes) I all the time have the same weird result on both of the devices. Initially near the sea shore - app works fine and CLLocationManager calls didUpdateLocations regularly and file has the initial track. After some distance from the starting point of swim (about may be 300-500 meters or may be after some time) CLLocationManager stops calling the delegate. When I get back to the ground it starts logging again, so the log is looking like this (this result I've seen on both of my devices iPhone 5, iPhone 6 and they kind of somehow syncronised in terms of when they stop tracking):


2015-05-31:09-14-47:-33.8324089860859:151.281617498166:5.0

2015-05-31:09-14-48:-33.8324103271904:151.281609283901:5.0

2015-05-31:09-14-49:-33.8324121712091:151.281615235052:5.0

2015-05-31:09-14-50:-33.8324131351279:151.281619342185:5.0

2015-05-31:09-14-51:-33.83241468578:151.281623533136:5.0

2015-05-31:11-17-35:-33.8396926742719:151.280322904884:65.0

2015-05-31:11-17-35:-33.8396926742719:151.280322904884:65.0

2015-05-31:11-17-35:-33.8396913678485:151.280324325015:65.0


Have anyone seen this before? May be I am doing something wrong? I've heard that there are some limitations for CoreLocation so that it can not be used at some higher altitudes (say to make weapons). But that should not be the case at sea, right?

You wrote:

delegate call didUpdateLocations uses beginBackgroundUpdateTask() / endBackgroundTask()


I do background track recording but I don't use background tasks. I just allow the location manager to use deferred location updates, and let the app get suspended if the OS so desires. Next time the device wakes up (if the user hits the Home button or some other event), your app will get the location updates for the whole period all at once.


The phone has no way of knowing whether it's on the ocean or not. If it has a view of the GPS satellites then tracking should continue. Do you see degraded accuracy on the last few readings before it stops recording? Perhaps it is losing the satellites?


I would also recommend putting a whole bunch of logging in your location handling code to make sure you aren't inadvertently discarding valid location updates due to a bug in any filtering code (discarding because they're "too old", insufficient accuracy, or whatever).

Thank you very much for your answer, that is actually really interesting idea. So the expected behaviour is to see all readings at once at the first call after I use the phone again - that might what I am doing wrong as I am taking only the lastObject.


You wrote |> Do you see degraded accuracy on the last few readings before it stops recording?

No, but what I see - when I open app again it starts logging again with degraded accuracy. So I guess I just need to take care about array of locations.

I don't think it would be a factor when swimming, but when you lose internet access, core location will take a while (tens of seconds, perhaps up to a minute or more) to get a position fix using only the GPS hardware. Once it gets the initial fix, it again updates normally. Could that be a factor? Are you testing in the water long enough to get past any events like that?


The other thing to check, are you asking core location to update continuously? There are some modes where it only updates when it detects significant changes in location. Check that. I don't use location in the background, but I recall that it also had some options/limitations. If for some reason the water or motion in water or change in GPS fix were at play, it could somehow be getting tricked into thinking there was no location change.

The app works definately longer than that. Say I run it for 2 hours (that is my normal swim time), but app tracks only first half an hour of it, not the whole thing.

I updated logging to capture all locations in delegate - it did not help. Still observing the same thing. Motion in the water is different - that is the fact, but in the car motion is different as well - and the app works in the car - just fine. May be it is a duration, can there be some sort of restriction to run location services no longer then an hour? Should not be as runners use it for much longer.


May be it just looses satelates without any significat elevation on top of water level.

CLLocationManager stops updating at sea
 
 
Q