I want to get a single location and then stop getting notification from CLLocationManager.
I do it with this:
-(id)initWithDelegate:(id <GPSLocationDelegate>)aDelegate{
self = [super init];
if(self != nil) {
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
delegate = aDelegate;
}
return self;
}
-(void)startUpdating{
locationManager.distanceFilter = kCLDistanceFilterNone;
locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters;
[locationManager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
[locationManager stopUpdatingLocation];
[delegate locationUpdate:newLocation];
}
The issue is that even when I do [locationManager stopUpdatingLocation];
in - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:
I still get notification, any idea why it happen?
Maybe try my solution. I'm build two functionals for handling LocationManger Obj.
The first function is startUpdates for handle start update location. Code look like this :
- (void)startUpdate
{
if ([self locationManager])
{
[[self locationManager] stopUpdatingLocation];
}
else
{
self.locationManager = [[CLLocationManager alloc] init];
[[self locationManager] setDelegate:self];
[[self locationManager] setDesiredAccuracy:kCLLocationAccuracyBestForNavigation];
[[self locationManager] setDistanceFilter:10.0];
}
[[self locationManager] startUpdatingLocation];
}
The second function is stopUpdate for handle CLLocationDelegate to stop update location. Code look like this :
- (void)stopUpdate
{
if ([self locationManager])
{
[[self locationManager] stopUpdatingLocation];
}
}
So, for CLLocationManagerDelegate should be look like this :
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
NSDate* eventDate = newLocation.timestamp;
NSTimeInterval howRecent = [eventDate timeIntervalSinceNow];
self.attempts++;
if(firstPosition == NO)
{
if((howRecent < -2.0 || newLocation.horizontalAccuracy > 50.0) && ([self attempts] < 5))
{
// force an update, value is not good enough for starting Point
[self startUpdates];
return;
}
else
{
firstPosition = YES;
isReadyForReload = YES;
tempNewLocation = newLocation;
NSLog(#"## Latitude : %f", tempNewLocation.coordinate.latitude);
NSLog(#"## Longitude : %f", tempNewLocation.coordinate.longitude);
[self stopUpdate];
}
}
}
Inside this function above, i'm correct only the best location for update location. I hope my answer will help, Cheers.
I think that the reason of your problem is in distance filter. As docs say:
Use the value kCLDistanceFilterNone to be notified of all movements. The default value of this property is kCLDistanceFilterNone.
So you just have what you've set - continuous updates.
Related
I am working on this walking/running app which calculates distance in meters and records lat-long for further use. Now when I calculate distance I get incorrect distance every time. I have compared it with other running apps and they generally show different distance than my distance.
Here is the code that I am using:
#define kDesiredAccuracy 5.0f
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
self.locationManager.distanceFilter = kDesiredAccuracy;
_routes = [[NSMutableArray alloc] init];
lastKnownLocation = nil;
-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
// return if accuracy is less than 0 or is greater than desired accuracy.
if (newLocation.horizontalAccuracy < 0)
{
return;
}
if(newLocation.horizontalAccuracy > kDesiredAccuracy)
{
return;
}
NSTimeInterval locationAge = -[newLocation.timestamp timeIntervalSinceNow];
CLLocationSpeed speed = [newLocation speed];
// return if stale data or user is not moving
if (locationAge > 5.0 || speed <= 0) return;
//return if first location is found
if(lastKnownLocation == nil)
{
lastKnownLocation = newLocation;
return;
}
CLLocationDistance distance = [newLocation distanceFromLocation:(self.pramDistance > 0)?lastKnownLocation:oldLocation];
if(distance > 0)
{
// save distance for future use
NSMutableDictionary *dict=[[NSMutableDictionary alloc] init];
[dict setObject:[NSString stringWithFormat:#"%g", newLocation.coordinate.latitude] forKey:#"latitude"];
[dict setObject:[NSString stringWithFormat:#"%g", newLocation.coordinate.longitude] forKey:#"longtitude"];
[dict setObject:[NSString stringWithFormat:#"%f",distance] forKey:#"distance"];
[_routes addObject:dict];
// add distance to total distance.
self.pramDistance += distance;
}
}
Once user finishes walking/running I draw rout of walk/run on map view. For this purpose I simply draw a ploy line over MKMapView using all the recorded locations.
The map view shows zig-zag line for route and distance is always incorrect. Please suggest me where I am doing wrong and what should I amend to make it work proper?
Here is the comparison (left one is other's app and right one is mine):
Try this,
Import CLLocationManagerDelegate,
CLLocation *currentLocation = self.currentLocation;
float distanceMile = [currentLocation distanceFromLocation:[[CLLocation alloc] initWithLatitude:latitude longitude:longitude]]/1609.34;
-(void)postCurrentLocationOfDevice
{
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.distanceFilter = kCLDistanceFilterNone;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[self.locationManager startUpdatingLocation];
self.locationManager.delegate = self;
}
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
self.currentLocation = [locations objectAtIndex:0];
[self.locationManager stopUpdatingLocation];
}
-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
self.currentLocation = newLocation;
[self.locationManager stopUpdatingLocation];
}
Though I didn't get much of the help here, I found some help and idea in this question: Corelocation incorrect distances
What I did to fix the problem is:
I stored recent 5 locations in an array.
Once 5 items are stored in the array, I checked for the nearest location.
After getting nearest location I calculated distance between last best location and stored new location in last best location.
P.S.: My code is messy and naming conventions are not that generic, that's why I am not posting my code here.
My ultimate goal is that i need to send lat and logitude to web server, every time when location changes.
I am using below code for sending lat and longitude of a device to a web server after every 2 minutes but it is not giving sometimes correct latitude and longitude as location changes.
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation
*)newLocation fromLocation:(CLLocation *)oldLocation
{
NSTimeInterval locationAge = -[newLocation.timestamp timeIntervalSinceNow];
NSLog(#"Location Age%#",[NSString stringWithFormat:#"%d",locationAge]);
if (locationAge > 5) return;
// test that the horizontal accuracy does not indicate an invalid measurement
if (newLocation.horizontalAccuracy < 0) return;
NSString *stringUrl;
// BOOL check = FALSE;
NSLog(#"Before condition condition");
if(bestEffortAtLocation == nil || bestEffortAtLocation.horizontalAccuracy > newLocation.horizontalAccuracy){
NSLog(#"condition");
self.bestEffortAtLocation = newLocation;
if (newLocation.horizontalAccuracy <= locmanager.desiredAccuracy) {
// we have a measurement that meets our requirements, so we can stop updating the location
// IMPORTANT!!! Minimize power usage by stopping the location manager as soon as possible.
[locmanager stopUpdatingLocation];
locmanager.delegate = nil;
}
//check = TRUE;
}
stringUrl = [NSString stringWithFormat:URLSAVELAT,stringUserId,[NSString stringWithFormat:#"%g",self.bestEffortAtLocation.coordinate.latitude],[NSString stringWithFormat:#"%g",self.bestEffortAtLocation.coordinate.longitude]];}
For location manager i am using below code
{
locmanager = [[CLLocationManager alloc] init];
[locmanager setDelegate:self];
locmanager.distanceFilter = 10.0;
//locmanager.distanceFilter = kCLDistanceFilterNone;
[locmanager setDesiredAccuracy:kCLLocationAccuracyBest];
[locmanager startUpdatingLocation];
}
Any,even small help would be appreciated, Thank u in advance
You should use the location update call backs from the API and use updateLocation method:
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
if([self.delegate conformsToProtocol:#protocol(CoreLocationControllerDelegate)]) {
[self.delegate locationUpdate:newLocation];
}
}
Then in the viewcontroller do this:
- (void)locationUpdate:(CLLocation *)location {
//DO WHATEVER YOU WANT HERE, INCLUDING SENDING TO SERVER
}
You also need to define two protocol methods, one of which is the locationUpdate:
#protocol CoreLocationControllerDelegate
#required
- (void)locationUpdate:(CLLocation *)location;
- (void)locationError:(NSError *)error;
#end
I would not recommend doing all that you do in the didUpdateLocation: method.
I am getting latitude, Longitude, Altitude, Accuracy, Speed from Location services.
I want to update all this information every 30 sec. For this purpose I've used a NSTimer:
[NSTimer scheduledTimerWithTimeInterval:30 target:self selector:#selector(locationUpdate:) userInfo:nil repeats:YES];
which I've put in the viewDidLoad method. It shows an output first time, but the second time, when the timer invokes this, it shows this error:
2011-08-02 13:17:00.141 CoreLocationAssign[1120:207] This is location <__NSCFTimer: 0x4b200a0>
2011-08-02 13:17:00.142 CoreLocationAssign[1120:207] -[__NSCFTimer coordinate]: unrecognized selector sent to instance 0x4b200a0
2011-08-02 13:17:00.144 CoreLocationAssign[1120:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFTimer coordinate]: unrecognized selector sent to instance 0x4b200a0'
*** Call stack at first throw:
The code is below:
MyCLController.h
#implementation MyCLController
#synthesize locationManager;
#synthesize delegate;
- (id) init{
if (self!=nil) {
self.locationManager = [[[CLLocationManager alloc] init] autorelease];
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
self.locationManager.distanceFilter = kCLDistanceFilterNone;
[self.locationManager startUpdatingLocation];
}
return self;
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
//NSLog(#"Location: %#", [newLocation description]);
[self.delegate locationUpdate:newLocation];
}
- (void)locationManager:(CLLocationManager *)manager
didFailWithError:(NSError *)error
{
// NSLog(#"Error: %#", [error description]);
[self.delegate locationError:error];
}
- (void)dealloc {
[self.locationManager release];
[super dealloc];
}
CoreLoactionController.h
- (void)viewDidLoad {
locationController = [[MyCLController alloc] init];
locationController.delegate = self;
[locationController.locationManager startUpdatingLocation];
[NSTimer scheduledTimerWithTimeInterval:30 target:self selector:#selector(locationUpdate:) userInfo:nil repeats:YES];
[super viewDidLoad];
}
- (void)locationUpdate:(CLLocation *)location {
locationLable.text = [location description];
CLLocationCoordinate2D coordinate = [location coordinate];
NSLog(#"This is location %#",[location description]);
NSLog(#"Lattitude = %#",[NSString stringWithFormat:#"%f", coordinate.latitude]);
NSLog(#"Langitude = %#",[NSString stringWithFormat:#"%f", coordinate.longitude]);
NSLog(#"Altitude = %#",[NSString stringWithFormat:#"%gm", location.altitude]);
NSLog(#"horizontalAccuracy = %#",[NSString stringWithFormat:#"%gm", location.horizontalAccuracy]);
NSLog(#"verticalAccuracy = %#",[NSString stringWithFormat:#"%gm", location.verticalAccuracy]);
NSLog(#"Speed = %#",[NSString stringWithFormat:#"%gm", location.speed]);
}
How ccan I solve this problem? I want to update the location every 30 sec.
There are better solutions than using a timer. CoreLocation has built in features for deferred updates and a timer combined with normal CoreLocation will destroy phone battery. Try allowDeferredLocationUpdatesUntilDistanceTraveled:timeout:
https://developer.apple.com/library/ios/documentation/CoreLocation/Reference/CLLocationManager_Class/CLLocationManager/CLLocationManager.html#//apple_ref/occ/instm/CLLocationManager/allowDeferredLocationUpdatesUntilTraveled:timeout:
In fact here :
- (void)locationUpdate:(CLLocation *)location
You're not receiving a CLLocation * but a NSTimer.
You should use the userInfo to transmit an object:
[NSTimer scheduledTimerWithTimeInterval:30 target:self selector:#selector(locationUpdate:) userInfo:location repeats:YES];
and
-(void)locationUpdate:(NSTimer*) timer{
//probably
CLLocation *location = (CLLocation*)[timer userInfo];
//...
}
Timer-based location updates are horrible battery eaters.
CoreLocation can tell you when the location gets changed, no need for polling. 30 seconds is much too slow if I'm even walking, and it needlessly destroys the battery if my phone is lying near my bed unmoved for many hours.
Hello im trying to get the latitude and longitude values where the the location of the user is
without having the map show up so basically it will run on the background. I guess i have to use the map kit but are there any examples?
If you don't want a map, you don't need MapKit. Just use CLLocationManager.
- (id) init {
if (self = [super init]) {
locationManager = [[CLLocationManager alloc] init];
[locationManager setDelegate:self];
[locationManager startUpdatingLocation];
}
return self;
}
- (void) locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)location fromLocation:(CLLocation *)oldLocation {
NSLog(#"lat:%f lon:%f", location.coordinate.latitude, location.coordinate.longitude);
}
I am new to iphone development.I am creating a map application.I have toolbar below the mapview with a button on it.On clicking the button it displays as an alert to load the current location.In my button click even i hava given code to find current location
-(IBAction) gosearch : (id) sender{
self.locationManager = [[[CLLocationManager alloc] init] autorelease];
self.locationManager.delegate = self;
[locationManager startUpdatingLocation];
}
For me it is not displaying the alert.What should i do?Please help me out. Thanks.
You need to have your controller class implement protocol CLLocationManagerDeligate. This will mean that it gets notified of errors or when the location is posted (for example – locationManager:didUpdateToLocation:fromLocation:)
Then you can pass on the long/lat and radius of view required to the MapView
Make sure for the alert view it looks like this-
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Current Location" message:#"Show Current Location?" delegate:nil cancelButtonTitle:#"Cancel" otherButtonTitles:#"OK"];
[alert show];
and also
- (void)alertView:(UIAlertView *)alertView willDismissWithButtonIndex:(NSInteger)buttonIndex
{
if (buttonIndex != [alertView cancelButtonIndex])
{
map.showsuserlocation = YES;
}
}
I'm not sure I fully understand your questions but here's what I have done to use the location manager.
First, I declare a class that implements CLLocationManagerDelegate
#interface GPSComponent <CLLocationManagerDelegate> {
CLLocationManager *locationManager;
CLLocation *currentLocation;
}
Then, in the class I have:
- (id) init {
locationManager = [[CLLocationManager alloc] init];
// Provide the best possible accuracy (this is the default; just want to write some code).
locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters;
// Must move at least 100 meters to get a new location update (default is get all notifications).
locationManager.distanceFilter = 100;
locationManager.delegate = self;
[locationManager startUpdatingLocation];
}
#pragma mark -
#pragma mark CLLocationManagerDelegate methods
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
// If you are about 400 miles south off the coast of Ghana, we might be ignoring your location information. We apologize.
// This is a lazy way to check for failure (in which case the struct is zeroed out).
if((fabs(newLocation.coordinate.latitude) > 0.001) || (fabs(newLocation.coordinate.longitude) > 0.001)) {
NSLog(#"Got location %f,%f", newLocation.coordinate.latitude, newLocation.coordinate.longitude);
if (currentLocation != nil) {
[currentLocation release];
}
currentLocation = newLocation;
[currentLocation retain];
}
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
NSLog(#"Location Manager error");
}
Then, to display a map with the user's location:
// Pull out the longitude and latitude and invoke google maps
- (IBAction)mapItButtonPressed {
NSString *url = [NSString stringWithFormat: #"http://maps.google.com/maps?q=%f,%f", (float)currentLocation.coordinate.latitude, (float)currentLocation.coordinate.longitude];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:url]];
}