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...
Related
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 have worked on one application name time tracker. User can manually swipe in and swipe out manually by clicking the button.
Now I would like to make it as automatic based on the location detection. For that I am using CLLocationManager class. It works fine sometimes and sometimes it gives wrong swipe details. I am using below code.
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.distanceFilter = kCLDistanceFilterNone;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
[locationManager requestWhenInUseAuthorization];
[locationManager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
_latitude.text = [NSString stringWithFormat:#"Latitude: %f", newLocation.coordinate.latitude];
_longitude.text = [NSString stringWithFormat:#"Longitude: %f", newLocation.coordinate.longitude];
if([_latitude.text doubleValue] > 17.76890) && [_longitude.text doubleValue] > 78.34567) {
if (isSwipeIn) {
isSwipeIn = false;
//necessary swipe out UI and logic
} else {
isSwipeIn = true;
//necessary swipe in UI and logic
}
}
}
Can anyone help me on this..
Instead of comparing lat-long, go for a range check like if your device is within few meter mark as swipe in otherwise swipe out.
You can check distance between two lat-long using following method in Objective-C
CLLocation *location; // Your Location to compare
CLLocation *currentLocation; // Your current location
double distance = [location distanceFromLocation:currentLocation]; // Returns distance in meters
// Now lets say you are within 5 meters mark Swipe In
if(distance <= 5)
// Mark swipe IN
else
// Mark swipe OUT
I hope this will help you. Happy coding :)
There is another way to do this, you can get distance from target location and check it with horizontalAccuracy of current location.
The delta gives you the distance between current location and targeted location. If delta is less than (<) horizontalAccuracy than current location is in a circle with a radius of horizontalAccuracy.
If delta is greater than (>) horizontalAccuracy than current location is far away than your targeted location.
So now CLLocationManager delegate method will be looks like below:
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
_latitude.text = [NSString stringWithFormat:#"Latitude: %f", newLocation.coordinate.latitude];
_longitude.text = [NSString stringWithFormat:#"Longitude: %f", newLocation.coordinate.longitude];
// Create Location object for your target location. e.g. (17.76890,78.34567)
CLLocation *targetLocation = [[CLLocation alloc] initWithLatitude:17.76890 longitude:78.34567];
CLLocationDistance delta = [newLocation distanceFromLocation:targetLocation];
if (delta > newLocation.horizontalAccuracy) {
if (isSwipeIn) {
isSwipeIn = false;
//necessary swipe out UI and logic
} else {
isSwipeIn = true;
//necessary swipe in UI and logic
}
}
}
Here is my location manager delegate code.
It is not giving speed when we move using car so at least speed value should change.
It always gives constant value -1.00.
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
CLLocation *crnLoc = [locations lastObject];
self.speedometerCurrentValue=crnLoc.speed;
self.lblSpeed.text=[NSString stringWithFormat:#"%f",crnLoc.speed];
}
Please check this screenshot from apple explanations. Your speed is invalid.
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+.
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
...
}