I'm in the process of writing an application that shows the user's distance from a fixed point as the user walks around (i.e. the label showing the distance from the user to the point is updated every time the user moves). I use a CLLocationManager with the code shown below:
- (void)viewDidLoad
{
locationManager=[[CLLocationManager alloc]init];
locationManager.distanceFilter = kCLDistanceFilterNone;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];
}
-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
CLLocationDistance meters = [newLocation distanceFromLocation:fixedPoint];
self.distanceLabel.text = [[NSString alloc] initWithFormat:#"Distance: %.1f feet", meters*3.2808399];
}
The label that is supposed to show the distance from the user to the point isn't updated constantly and when it is updated, it doesn't usually show the correct distance from the user to the fixed point. I was wondering if there is a better way for me to try and do this, or do the fundamental limitations of the core location framework make this impossible. Any help will be greatly appreciated.
Are you filtering out old (cached) positions? You should also filter based on accuracy, you probably don't want low accuracy locations.
You won't get continous or periodic update, the callback only occurs when the location has changed.
Assuming the device has GPS and can see enough GPS satellites to get a good position, this works fine.
-(void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation {
NSTimeInterval age = -[newLocation.timestamp timeIntervalSinceNow];
if (age > 120) return; // ignore old (cached) updates
if (newLocation.horizontalAccuracy < 0) return; // ignore invalid udpates
...
}
Related
My code is for a Golf player app. I need the exact user location here is my present code
- (void) update_location
{
locationManager_player = [[CLLocationManager alloc] init];
locationManager_player.delegate = self;
locationManager_player.desiredAccuracy = kCLLocationAccuracyBest;
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0) {
[locationManager_player requestWhenInUseAuthorization];
}
[locationManager_player startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
// Code to handle the current user location
}
The above delegate method is not giving the exact user location. Perhaps this gives the coordinates which are 30 to 40 yards far from user current position
Thanks in advance
Location accuracy is controlled by the desiredAccuracy property of CLLocationManager. Check what is set in your case. Default value is kCLLocationAccuracyBest. You can set it to kCLLocationAccuracyBestForNavigation but it require more power requirements.
More detail here.
How do I get the best Accuracy Indoor GPS Co-ordinates in device? Whenever I am launching the application in same location, the GPS value gets different different coordinates values. If, I will get the Proper coordinates, then only I can calculate the actual distance between the two coordinates and navigate a user.
Here my sample code:
_locationManager = [[CLLocationManager alloc] init];
_locationManager.delegate = self;
_locationManager.desiredAccuracy = kCLLocationAccuracyBest;
_locationManager.distanceFilter = kCLHeadingFilterNone;
[self.locationManager startUpdatingLocation];
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
userLat = newLocation.coordinate.latitude;
userLon = newLocation.coordinate.longitude;
}
#batMan007 this is the best result you can get from the gps. You might be able to get a more accurate coordinate by connecting to a wifi network. Besides, if you are very particular about the distance in terms of meters, perhaps iBeacon is your only option.
I need to calculate ALL gps parameters in my program so I use this piece of code:
(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
CLLocation* loc = [locations lastObject];
which collects all the gps measurements (altitude, speed, etc) in loc object and I have the lat/long info (loc.coordinate.lattitude and loc.coordinate.longitude) but these are the NEW measured coordinates.
As I also want to calculate distance between measurements how can I retrieve both the "new" coordinates and the "old" coordinates from the didUpdateLocations method?
If I add another locationManager call with the didUpdateToLocation method in the program (which will give old and new coordinates):
(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation {
the initial locationManager method (didUpdateLocations) is not called at all, so I cannot calculate all gps data plus distance...
After succeeding with the property copy I have this working code but I cannot make sense of:
(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
_locManagerIteration++;
NSLog(#"Location manager iteration = %ld", _locManagerIteration);
CLLocation* loc = [locations lastObject]; // locations is guaranteed to have at least one object
if (_locManagerIteration == 1) { //INITIALIZE THE FIRST PAST COORDINATE OBJECT
self.pastCoordinate = [locations lastObject];
} else {
CLLocationDistance _pointDistance = [self.pastCoordinate distanceFromLocation:loc];
NSLog(#"POINT TO POINT DISTANCE = %f", _pointDistance);
self.pastCoordinate = [locations lastObject];
}
NSLog(#"POINT TO POINT DISTANCE = %f", _pointDistance);
_totalDistance = _totalDistance + _pointDistance; //COMPUTE TOTAL DISTANCE
_totalDistance = _totalDistance / 1000; //TRANSLATE TOTAL DISTANCE IN KILOMETERS
In the above section, CLLocationDistance call correctly places the distance in meters in my global variable _pointDistance. I print the _pointDistance variable and see the number (NSLog...). HOWEVER, when I again print the same global variable outside the if-then statement the value is always zero...
Within the else bracket the _pointDistance variable has a black color in XCODE (and prints the value) and outside the else bracket is showed with green color and the value is zeroed.... Can't make any sense out of it...
I am using CoreLocation to grab the users location. I need to grab the users location then send that to the server. I have it all working, but! I am implementing locationManager:(CCLLocationManager *)manager...
My url request is hitting before the location is found. Whats the best way to:
Request location
Store in string
Send string to request
I want to ensure the location is found before its sent. Do I check against the instance of the class with a conditional and inside the block hit the server. I dont need to keep updating, just grab once and stopUpdatingLocation
Was going through this post previously: Getting Longitude/Latitude of the User When the viewDidLoad
What I have so far:
- (void)viewDidLoad {
[super viewDidLoad];
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers;
[locationManager startUpdatingLocation];
...more below... server request below here
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
NSLog(#"didUpdateToLocation: %#", newLocation);
CLLocation *currentLocation = newLocation;
if (currentLocation != nil) {
NSLog(#"found!");
[locationManager stopUpdatingLocation];
}
}
Thoughts on how to do that? I think the conditional may work, but not sure if there was a proper way to handle that using the methods provided from CoreLocation.
Create a new method that will perform your location-dependent code. Then once you have the location (I.e. After the NSLog(#"found!"); line), call this method.
Note that the method may get called multiple times as the location accuracy improves - you might want to handle this.
For example:
- (void)viewDidLoad {
[super viewDidLoad];
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers;
[locationManager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
NSLog(#"didUpdateToLocation: %#", newLocation);
CLLocation *currentLocation = newLocation;
if (currentLocation != nil)
{
NSLog(#"found!");
[self handleLocation:newLocation];
[locationManager stopUpdatingLocation];
}
}
- (void)handleLocation:(CLLocation*)location
{
// handling code here
}
The location manager is asynchronous. You have to ask for location updates, then wait for it to call you back.
Worse, the first several updates are usually garbage that needs to be thrown away.
The first location update frequently has a timestamp that is hours, days, or even weeks old. You first have to check to make sure the timestamp is in the last few seconds.
Once you've done that, you need to check the horizontal accuracy, and make sure the reading is accurate enough. Often when you first start the location manager the first few readings have an accuracy value of more than a kilometer, which is awful. (Accuracy is really a radius value. You can only be sure that the location you get is somewhere inside a circle with the specified radius.) You need to come up with an app-specific accuracy reading that is "good enough", and throw away accuracy readings until you get one that is good enough. You also need to check for negative accuracy readings, which mean that the GPS is returning invalid values.
Next, you have to allow for the case where the GPS doesn't settle down in a reasonable time. (Sometimes it can take multiple minutes, or simply fail to get a good reading.) In that case you need to handle it as a failure.
So, to handle all that you need to write your locationManager:didUpdateLocation: method to check the time stamp and the horizontal accuracy to make sure the reading is actually good. You also need to make sure you time out and report a failure if you can't get a decent location reading after a reasonable wait. One way to do this is to start a "give up" timer when you first begin location updates, and after you get a good reading, kill it. If the timer fires, stop location updates and report a "can't get a good location reading" error to your user. Understand that it's not uncommon to take 10 or 15 seconds to get a decent accuracy reading.
I use this code to get the longitude and latitude.
(void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation {
NSLog(#"%f",newLocation.coordinate.latitude);
self.location = newLocation;
}
But the longitude and latitude which i got has the excursion with the actual geographical position. How to solve this problem?
You should be testing the accuracy of the CLLocation object that is returned, and making sure it meets your location accuracy criteria.
if (newLocation.horizontalAccuracy > 1000) {
// Throw away this location and wait for another one as this is over 1km away
}
Also, the locationManager:didUpdateToLocation:fromLocation: method has been deprecated in iOS6 so you should use locationManager:didUpdateLocations: if you're targetting iOS6+.