2

GPS signal is lost when App is resumed from long time suspend mode.
And/or after user goes into a building where GPS is weak and then resumes the App.

The blue dot disappears and the map is centered at lat:0 long:0 ( which is somewhere in the ocean near Nigeria-Africa ) If you launch another GPS app at that point in time, such as Apple Maps, you DO see the blue dot, even if not so accurate.

The only way a user can fix it - is by killing my app completely and start it again.

It happens on both iOS 5.x and iOS 6.x.

Before going into details, I would really like to ask:
Does anyone encounter this problem ??
Its very annoying but, I couldn't find anyone complaining about this anywhere on the web - very weird.

I'm using normal CLLocation with showUserLocation=YES,
Nothing magical, no special accuracy tuning or whatever, just simple default implementation.

I have already tried restarting every possible component when App is resumed;

showUserLocation=NO;
showUserLocation=YES;

or

[locationManager stopUpdatingLocation];
[locationManager startUpdatingLocation];

or even releasing locationManager and initialize it again doesn't help!
( also tried restarting it with a delay using dispatch_after )

Is there any programmatic way to force RESET the GPS signal or CLLocation in ios ?
Will appreciate any relevant discussion!

AmitP
  • 5,353
  • 4
  • 35
  • 27
  • I've seen something similar occasionally, but not during suspend and resume, usually between launches. – gaige Mar 23 '13 at 13:24

2 Answers2

1

I Think you default Location is set "None" so this type of issue created.

Go to 

Edite Scheme..
    |
    |
  "Run YourProjectName"  / Left Hand Side
       |
       |
  Select "Option" Tab
         |
         |
     Default Location
          |
          |
     Choose any Location such like , "London England"
iPatel
  • 46,010
  • 16
  • 115
  • 137
  • Yes, it was set to None, I did the change and started testing. will report soon. – AmitP Mar 23 '13 at 18:47
  • It certainly improved the GPS recovering abilities after an App resume. The only down side of this, is when testing on a device connected to Xcode, it will simulate London or whatever as it's real GPS coordinates. – AmitP Aug 24 '13 at 23:14
0

When you say that you've tried stopping/starting the CLLocationManager object, are you saying that the call-back you get in your delegate gives you a 0,0 coordinate, or are you trying to access the location directly using the location property in CLLocationManager?

I work on a location based app and one thing I can tell you is that you cannot count of directly getting the location of a CLLocationManager object. The only reliable way to get location information is to rely on the callback of the CLLocationManager class by implementing

-(void) locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation

The way I handle CLLocationManager in my app (now I'm not saying this is optimal or ideal for your use case but it does allow us to provide a solid location-based experience to the user on app launch/resume)

  1. Wrap the CLLocationManager into a location management class (usually using a singleton) - I think this can be a subclass of CLLocationManager but in my case it's just a subclass of NSObject with a CLLocationManager object as a property
  2. Store the last known valid location in this singleton, and then write it to disk (NSUserDefaults or another location - need to re-check if you're allowed to store user location in NSUserDefaults but we've done it in our app and doesn't seem to affect the approval process)
  3. Re-implement a way to get the current location in your custom class - basically check if CLLocationManager is returning 0,0 and if it is, return your cached position instead
  4. Not strictly necessary but if you have multiple views/pages that need to use the location, implementing the observer model works well (since your singleton is now CLLocationManager's delegate, you need to have a way to pass this information on to your view controllers).

With the above, on my map page (or wherever I'm displaying user location) - I basically update the map with the cached location once (in viewDidLoad) and then I allow one update to the map through the delegate-callback. Once that call-back is received, I then set showsUserLocation to YES (if the call-back isn't called, then you don't have a valid location yet and so setting showsUserLocation at that point doesn't do anything).

I hope this helps and feel free to let me know if you have any further questions!

Jai Govindani
  • 3,181
  • 21
  • 26
  • Thanks for sharing your app design, it sounds like a firm solution in deed. When I say 0,0 I do mean this what I get by the callback. And the blue dot is gone for good from this stage. If you could please explain the method of which you create/fake user location (with real blue dot and default annotation?) in step 3. – AmitP Mar 23 '13 at 23:27
  • If you want to mock the default annotation, the easiest way to do this would be to use Sam Vermette's https://github.com/samvermette/SVPulsingAnnotationView - he's an awesome coder and every class I've used of his has always been dead-simple to implement (SVProgressHUD, SVPullToRefresh, SVInfiniteScrolling). Just put that at the cached location (assuming you cached location to disk before the app went into the background). – Jai Govindani Mar 25 '13 at 05:22