CLLocationManager weird issues - iphone

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 .

Related

didUpdateToLocation called multiple times

I have an application in which user track his/her route when jogging or cycling, So i need perfect location, so user's routes will be perfect.
But, I have one problem in this,
locManager = [[CLLocationManager alloc] init];
[locManager setDesiredAccuracy:kCLLocationAccuracyBestForNavigation];
[locManager setDelegate:self];
[locManager startUpdatingLocation];
In viewDidLoad. Using this didUpdateToLocation method called multiple times when I just dont move device a little and on map very strange route draw.
I just cant understand why this happen, if I am doing some wrong or missing something.
Thanks.......
I use locationManager.distanceFilter = 500; (or so) // meters
to prevent multiple calls from happening. just remember to call this BEFORE you start updating your location
You can set the distancefilter of the location manager hope this may help you
locationManager=[[CLLocationManager alloc] init];
locationManager.delegate=self;
locationManager.desiredAccuracy=kCLLocationAccuracyNearestTenMeters;
locationManager.distanceFilter=10.0;
[locationManager startUpdatingLocation];
When you first start location services, you'll generally see multiple location updates come whether you're moving or not. If you examine the horizontalAccuracy of the locations as they come in, you'll see that while it's "warming" up it will show a series of locations with greater and greater accuracy (i.e. smaller and smaller horizontalAccuracy values) until it reaches quiescence.
You could disregard those initial locations until horizontalAccuracy falls below a certain value. Or, better, during start up, you could disregard the previous location if (a) the distance between a new location and the old location is less than the horizontalAccuracy of the old location and (b) if the horizontalAccuracy of the new location is less than that of the prior location.
For example, let's assume you're maintaining an array of CLLocation objects, as well as a reference to the last drawn path:
#property (nonatomic, strong) NSMutableArray *locations;
#property (nonatomic, weak) id<MKOverlay> pathOverlay;
Furthermore, let's assume your location update routine is just adding to the array of locations and then indicating that the path should be redrawn:
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
NSLog(#"%s", __FUNCTION__);
CLLocation* location = [locations lastObject];
[self.locations addObject:location];
[self addPathToMapView:self.mapView];
}
Then the addPathToMapView can therefore remove the second from last location if it's less accurate than the last one and if the distance between them is less than the most recent location's accuracy.
- (void)addPathToMapView:(MKMapView *)mapView
{
NSInteger count = [self.locations count];
// let's see if we should remove the penultimate location
if (count > 2)
{
CLLocation *lastLocation = [self.locations lastObject];
CLLocation *previousLocation = self.locations[count - 2];
// if the very last location is more accurate than the previous one
// and if distance between the two of them is less than the accuracy,
// then remove that `previousLocation` (and update our count, appropriately)
if (lastLocation.horizontalAccuracy < previousLocation.horizontalAccuracy &&
[lastLocation distanceFromLocation:previousLocation] < lastLocation.horizontalAccuracy)
{
[self.locations removeObjectAtIndex:(count - 2)];
count--;
}
}
// now let's build our array of coordinates for our MKPolyline
CLLocationCoordinate2D coordinates[count];
NSInteger numberOfCoordinates = 0;
for (CLLocation *location in self.locations)
{
coordinates[numberOfCoordinates++] = location.coordinate;
}
// if there is a path to add to our map, do so
MKPolyline *polyLine = nil;
if (numberOfCoordinates > 1)
{
polyLine = [MKPolyline polylineWithCoordinates:coordinates count:numberOfCoordinates];
[mapView addOverlay:polyLine];
}
// if there was a previous path drawn, remove it
if (self.pathOverlay)
[mapView removeOverlay:self.pathOverlay];
// save the current path
self.pathOverlay = polyLine;
}
Bottom line, just get rid of locations that are less accurate than the next one you have. You could get even more aggressive in the pruning process if you want, but there are tradeoffs there, but hopefully this illustrates the idea.
startUpdatingLocation
Will continuously update a user's location even when the location does not change. You just need to structure your app to handle these continuous updates according to your needs.
Try reading Apple's documentation on this subject. It is confusing at first but try anyway.
http://developer.apple.com/library/ios/#documentation/UserExperience/Conceptual/LocationAwarenessPG/CoreLocation/CoreLocation.html#//apple_ref/doc/uid/TP40009497-CH2-SW1
I think this is what you need.startMonitoringForRegion:desiredAccuracy
for Example see the following github link.
Try this Bread Crumb sample code provided by Apple..
http://developer.apple.com/library/ios/#samplecode/Breadcrumb/Introduction/Intro.html
Add this,
[locManager stopUpdatingLocation];
into your updateUserLocation delegate method.
Review the following code snippet:
-(void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
[_locationManager stopUpdatingLocation];
}
locationManager.startUpdatingLocation() fetch location continuously and didUpdateLocations method calls several times,
Just set the value for locationManager.distanceFilter value before calling locationManager.startUpdatingLocation().
As I set 200 working fine
locationManager.distanceFilter = 200
locationManager.startUpdatingLocation()

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 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];

I can't get the gps coordinates for a persistent period of time

I have implemented the standard method of retrieving the coordinates from the gps using - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation.
The problem is that this function is called only on initialization and not throughout the life of the program. Is this normal?
In android you would implement a listener and you would get data instantly.
Is this not the wright way how i'm doing it? If it is, what could be the problem? (btw i've checked, i don't stopUpdatingLocation)
I have a CLLocationManager inherited class named testing and initialize it
testing* cllm = [[testing alloc] init];
cllm.delegate = self;
i later start the updating
[cllm startUpdatingLocation];
self.locationManagerDelegate = delegate;
and later is called
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
but after that it isn't called anymore. I need it to be called frequently so that i may calculate the distance to a certain point X from where i am.
Agreed with #Matt, without more code the best solution I can offer is this to tell it to update every time the device is moved with:
[self.locationManager setDistanceFiler:kCLDistanceFilterNone]
Update
I went through past projects and found the code I believe you are looking for assuming your location manager subclass is working properly
- (void)viewDidLoad {
[super viewDidLoad];
//Location
// create new location manager
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
self.locationManager.distanceFilter = kCLDistanceFilterNone;
// start location manager
[self.locationManager startUpdatingLocation];
}
-(void) distanceBetweenUserandPin {
CLLocation *currentUserLocation = [[CLLocation alloc] initWithLatitude:_currentLocation.latitude longitude:_currentLocation.longitude];
CLLocation *currentPinLocation = [[CLLocation alloc] initWithLatitude:_pinLocation.latitude longitude:_pinLocation.longitude];
CLLocationDistance distanceBetweenUserAndPinMeters = [currentUserLocation distanceFromLocation:currentPinLocation];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation{
//This successfully saves Lat, Long Data to a point location
CLLocationCoordinate2D location = CLLocationCoordinate2DMake(newLocation.coordinate.latitude, newLocation.coordinate.longitude);
NSLog(#"%f, %f", location.latitude, location.longitude);
//This assigns the value of location to the ivar _currentLocation
_currentLocation = CLLocationCoordinate2DMake(location.latitude, location.longitude);
NSLog(#"%f, %f", _currentLocation.latitude, _currentLocation.longitude);
}
First, it seems strange to me that you would use a subclass of CLLocationManager, since I'm not sure what benefit that provides you. Assuming that's not the problem, however...
From the CLLocationManager documentation:
This method returns immediately. Calling this method causes the
location manager to obtain an initial location fix (which may take
several seconds) and notify your delegate by calling its
locationManager:didUpdateToLocation:fromLocation: method. After that,
the receiver generates update events primarily when the value in the
distanceFilter property is exceeded. Updates may be delivered in other
situations though. For example, the receiver may send another
notification if the hardware gathers a more accurate location reading.
What's happening is that it is being called once for the initial position fix, but it isn't calling again because other conditions haven't changed. If a user doesn't move anywhere, then new location data won't be provided since it will be the same as last time (with a few exceptions as mentioned in the docs).
When you're testing your app, make sure that you try moving around and changing your location to produce an update. If that doesn't work, try experimenting with the desiredAccuracy and distanceFilter properties:
You start standard location services by calling the
startUpdatingLocation method. This service is most appropriate for
applications that need more fine-grained control over the delivery of
location events. Specifically, it takes into account the values in the
desiredAccuracy and distanceFilter property to determine when to
deliver new events.
Other than that, I'd guess it might have to do with how you're subclassing CLLocationManager. Providing some of that code might help.

how to get current latitude & longitude

How to get current latitude & longitude
without
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation*)newLocation fromLocation:(CLLocation *)oldLocation {
}
using this method
and if i used this function , how much distance i have to travel.... so that this method will be called by corelocation framework or can i call this function programmatic ....
The CLLocationManager is the interface you must use in order to get information about the location of the device.
You can initialise and begin getting location updates whenever you like. The CLLocationManager will notify your delegate whenever a new location is received.
locationManager = [[CLLocationManager alloc] init];
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
locationManager.distanceFilter = DISTANCE_FILTER_VALUE;
locationManager.delegate = self;
[locationManager startUpdatingLocation];
Note that when you try to get the values while using a simulator and do:
nsLog(locationManager.location.coordinate.latitude); // it will give you zero
And if you use the mapkit to get the lat and long it will give you the coordinates of apple main office (If im not mistaken).
I thought that it take so much time before it actually gets your location but when I try to run it in the actual device it prompts the allow device to get current location immediately.