CLLocationManager heading issues on iPhone 5 - iphone

I recently started testing my app on an iPhone 5, and to my alarm, it seems that the CLLocationManager doesn't really work! Although [CLLocationManager headingAvailable] is YES, I don't receive any heading updates at all. Strangely, on an iPhone 4, after 30 or so heading updates, locationManager:didUpdateToHeading: is no longer called. This issue is entirely new. The location manager also returns negative numbers for verticalAccuracy, so I'm assuming the altitude it is invalid. Here's how I'm creating the location manager:
CLLocationManager* locationManager = [[CLLocationManager alloc] init];
if([locationManager respondsToSelector:#selector(disallowDeferredLocationUpdates)]) {
[locationManager disallowDeferredLocationUpdates];
[locationManager setPausesLocationUpdatesAutomatically:NO];
}
locationManager.headingOrientation = CLDeviceOrientationFaceUp;
locationManager.distanceFilter = kCLDistanceFilterNone;
locationManager.headingFilter = -1;
locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
[sharedSingleton setLocationManager:locationManager];
sharedSingleton is just my singleton class that handles some odds and ends, including holding onto a reference to the location manager.
If I need to post any more code let me know. I just don't know what might be causing this strange issue. Thanks!

You need to retain "locationManager" in memory somewhere, either as a property of your object or as an instance variable.
What I belive is happening is that you're creating your location manager, and then your method exits and "locationManager" falls out of scope and is magically released by ARC.
So, instead, do something like this:
in your #implementation:
#property (strong) CLLocationManager * locationManager;
and in your #interface:
self.locationManager = [[CLLocationManager alloc] init];
if([self.locationManager respondsToSelector:#selector(disallowDeferredLocationUpdates)]) {
[self.locationManager disallowDeferredLocationUpdates];
[self.locationManager setPausesLocationUpdatesAutomatically:NO];
}
self.locationManager.headingOrientation = CLDeviceOrientationFaceUp;
self.locationManager.distanceFilter = kCLDistanceFilterNone;
self.locationManager.headingFilter = -1;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;

You could try a few things. First of all, I don't see a startUpdatingHeading call. Maybe you're doing it somewhere else. You should add the locationManager:didFailWithError: method to the delegate to check for errors, and try returning YES in locationManagerShouldDisplayHeadingCalibration: in case it's a calibration issue.

Seems the solution was obvious and I overlooked it. The delegate was being set to nil just moments after the location manager was started, which explains why on a slower device like the iPhone 4 a few updates were able to come through before the code setting the delegate to nil was run, but on the iPhone 5 it was instantaneous.

Related

Location still monitoring after locationManager = nil and stopUpdatingLocation called

I'm trying a lot of things to stop the location update of my app but nothing seems work…
What I do (regard of the post : StopUpdatingLocation method not working for iOS5) :
// Initialise my locationManager and start monitoring :
locationManager = [[CLLocationManager alloc] init];
[locationManager startUpdatingLocation];
// .. Some code to use the coordinates that locationManager gives me.
// To stop monitoring :
locationManager = nil;
You have to know I placed [locationManager stopUpdatingLocation]; in the method :
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
So the location is updated only 1 time (btw tell me if it's a good idea…).
I also tried to place [locationManager stopUpdatingLocation]; just before locationManager = nil; in the main code, but the blue dot that gives me my location is still moving on my map in both cases…
I also set a timer which print the locationManager object in the console, and it gives me (null) meanwhile the blue dot is still moving on my iPhone 5 so I don't understand that…
Or maybe the dot is still moving because of another thing, but not because of locationManager update ?
I'm certainly missing something but I don't get what :/.
Thanks for ideas and help.
One possibility: The blue dot moving on your map is because you set the MKMapView's showsUserLocation to YES. It will track until you set it to NO.
Another possibility: This line is wrong:
locationManager = nil;
That does not stop monitoring, but it does cause you to be unable to refer to the location manager, so now you can't stop monitoring! Cut that line.
I faced the same problem that even after I placed the code
[locationManager stopUpdatingLocation];
locationManager=nil;
my application was using GPS service which was un-necessarily consuming battery power. the solution for this problem is to turn off the showUserLocation property of MKMapView .
[self.mapView setShowsUserLocation:NO];
Since the MKMapView keeps on using your GPS service even if the LocationManager is nil.
Hope it will help you
Use this lines of code
[self.locationManager stopUpdatingLocation];
self.locationManager.delegate = nil;
self.locationManager = nil;
Thanks!

CLLocationManager didUpdateToLocation not being called after some time

I am trying to record a users location over time. If the user is on the move it works fine and the delegate method didUpdateToLocation is invoked reliably.However if the user is stationary and the app is running in the background then after some time, the delegate method is no longer invoked. To restart it, the app needs to be bought into the foreground. Once it is active the delegate method is invoked reliably again.
I initially thought that this could be due to the fact that the CLLocationManager object was declared within a ViewController, so I changed it to be declared within the AppDelegate but that did not help either.
I have also experimented with the distanceFilter property to no avail. I am currently setting it up using the following code from within a View controller. Note that the object itself is declared and initialized in the AppDelegate object.
app.locationManager.delegate = self;
app.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
app.locationManager.distanceFilter = kCLDistanceFilterNone;
[app.locationManager startUpdatingLocation];
Has anyone else run into this issue? Any pointers would be appreciated. I have been struggling with this for a few days now.
iOS 6 introduces the CLLocationManager property pausesLocationUpdatesAutomatically. It needs to be set to NO when you set up your CLLocationManager, as described here: http://www.stackoverflow.com/a/12781634/700769
Add this code in UpdateLocation method
- (void) updateLocation{
self.locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.pausesLocationUpdatesAutomatically = NO;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
if ([CLLocationManager locationServicesEnabled]) {
[locationManager startUpdatingLocation];
} else {
NSLog(#"Location services is not enabled");
}
}
also edit setting in Schemes: Scheme/Edit Scheme/Options/Allow Location Simulation checked but don't have a default location set.
You need to add location in UIBackgroundModes at app plist file.
if #available(iOS 9.0, *){
locationManager.allowsBackgroundLocationUpdates = true;
}

CLLocationManager won't stop updating

Here is my code:
- (void) viewWillAppear:(BOOL)animated
{
// SETUP THE LOCATION MANAGER.
self.locManager = [[CLLocationManager alloc] init];
self.locManager.delegate = self;
[self.locManager startUpdatingLocation];
}
- (void) viewWillDisappear:(BOOL)animated
{
[self.locManager stopUpdatingLocation];
[self.locManager.delegate release];
}
When the View Controller exits the CLLocationManager arrow logo in the top right corner is still showing. This is both on iOS 4.3 and 5.0. Any explanation?
I believe the system indicates the location badge on any app that has used Core Location in last hour or so.
The purple arrow should disappear as soon as you call:
[self.locManager stopUpdatingLocation];
While allocating your locManager, you need not call self.locManager. That will bump up the retain count to 2. Instead use:
locManager = [[CLLocationManager alloc] init];
Also, put a breakpoint in your viewWillDisappear: method and make sure it does get called. Also, set the delegate to nil at the end.
After following these points, your code shall work.
The purple arrow is for Location Services and consumes battery heavily. Make sure the arrow disappears as soon as you call stopUpdatingLocation:

CLLocationManager not stopping/releasing

I'm using MKMapView and I start the map at the last known location with CLLocationManager, the problem is that the iPhone and Location Services reports that I'm still using the services after I'm done which rises some concerns about battery usage.
So, please help me release this properly.
CLLocationManager * MANG = [[CLLocationManager alloc] init];
[MANG startMonitoringSignificantLocationChanges];
if(MANG.location){
[mapa setCenterCoordinate:MANG.location.coordinate animated:NO];
}
[MANG stopMonitoringSignificantLocationChanges];
[MANG stopUpdatingLocation];
[MANG release];
There are two ways to fetch the location using Location Services: the first one, less accurate but more battery friendly; and the second one more accurate.
When you declare [myLocationManager startMonitoringSignificantLocationChanges] your iPhone checks for location every time you left a cell tower and enter into a new one.
When you declare [myLocationManager startUpdatingLocation] your iPhone checks for location every time the GPS detects a position change (maybe each 1-3 meters, depending on accuracy).
So the thing is, in your code you’re trying to stop the declared Location Manager twice. Just remove the second stop instruction and you’ll get the correct code:
CLLocationManager * MANG = [[CLLocationManager alloc] init];
[MANG startMonitoringSignificantLocationChanges];
if(MANG.location){
[mapa setCenterCoordinate:MANG.location.coordinate animated:NO];
}
[MANG stopMonitoringSignificantLocationChanges];
[MANG release];

CLLocationManager weird issues

I have a MKMapView whereby I drop an annotation everytime the view loads, or when showLocation custom class method is called.
I need the accuracy to be the best
-(void)viewDidLoad {
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.distanceFilter = kCLDistanceFilterNone;
locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
[locationManager startUpdatingLocation];
}
-(IBAction) showLocation:(id) sender{
[locationManager startUpdatingLocation];
}
- (void) locationManager:(CLLocationManager *) manager
didUpdateToLocation:(CLLocation *) newLocation
fromLocation:(CLLocation *) oldLocation {
// start geocoding with newLocation coordinate which will automatically set annotation.
SVGeocoder *geocodeRequest = [[SVGeocoder alloc]
initWithCoordinate:CLLocationCoordinate2DMake(newLocation.coordinate.latitude, newLocation.coordinate.longitude)];
[geocodeRequest setDelegate:self];
[geocodeRequest startAsynchronous];
[geocodeRequest release];
[locationManager stopUpdatingLocation];
}
My question is when will the didUpdateToLocation method be called? Only after a new location is found when I perform [locationManager startUpdatingLocation]?
I am facing some weird issue when the user is travelling and on stationary.
Say the user is travelling from point A->B->C->D with 1 min intervals between points. When I call my method at point C, sometime it returns the coordinates of point A, sometimes point B and sometimes C. It's just random.
It's even more weird when I am on stationary. I get different coordinates when I calls showLocation method even though I am hooked up on my house WiFi.
I was thinking of implementing the didUpdateToLocation to get the best result it can within 5secs. If within the 5secs, it finds a particular location of an accuracy I had defined, then use the coordinate. If not, use the best it has found within the 5sec time frame. But as I am new I am not sure how to code something like that. I read up NSTimer and it seems like it might work.
Any advices guys?
Thanks a lot in advance!
One of the reasons you are receiving the location from point A is that CoreLocation is returning the last valid location it had first until it can obtain a more accurate location. When you call [locationManager startUpdatingLocation]; it will return the -didUpdateToLocation over and over until you are statisfied and finally call -stopUpdatingLocation.
I think you just need to allow a bit of time for it to get a better location fix before you stop updating your location. I would consider moving the stop updating location from your -didUpdateToLocation to a different method.
Remove [locationManager stopUpdatingLocation]; from your code and try .