Latitude Longitude IOS 4.3 - objective-c

I´m following the http://www.switchonthecode.com/tutorials/getting-your-location-in-an-iphone-application tutorial, but I can´t not get mi latitude and longitude in my Xcode SDK.
- (void)viewDidLoad {
[super viewDidLoad];
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
[locationManager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
int degrees = newLocation.coordinate.latitude;
double decimal = fabs(newLocation.coordinate.latitude - degrees);
int minutes = decimal * 60;
double seconds = decimal * 3600 - minutes * 60;
NSString *lat = [NSString stringWithFormat:#"%d° %d' %1.4f\"",
degrees, minutes, seconds];
//latLabel.text = lat;
degrees = newLocation.coordinate.longitude;
decimal = fabs(newLocation.coordinate.longitude - degrees);
minutes = decimal * 60;
seconds = decimal * 3600 - minutes * 60;
NSString *longt = [NSString stringWithFormat:#"%d° %d' %1.4f\"",
degrees, minutes, seconds];
NSLog(#"%# %#",longt, lat);
}
It don´t show me the latitude and longitude in the Console.
Help me please.

Your code looks fine. If it does not work - the issue is not here.
Make sure:
You running it on a device (not emulator)
Your device has SIM installed and connected to cellular network
It's very good idea to have the device connected to WiFi with Internet access.
All these things will help GPS to fix the position faster using assisted GPS.
Also, take into account that Core Location returns last known position almost immediately. It's stale and may be wrong, but provided immediately. If do not getting anything at all - it looks like the issue with Core Location on your device, not with the application.
Also, it's good idea to implement locationManager:didFailWithError: method to catch possible errors. Like disabled GPS.
Here is example for this method:
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
NSLog(#"GPS Error: %#", [error localizedDescription]);
}
GPS position fixing may take few minutes for 3Gs and early, and about 10 seconds for 4 and 4S (assuming clear sky view in both cases)

Related

CLLocationCoordinate2D returns integers for latitude and longitude instead of double

I'm using CLLocation to get the current location as follows:
-(void)loadCurrentLocation{
if (manager==nil) {
manager=[[CLLocationManager alloc]init];
}
manager.delegate=self;
manager.desiredAccuracy=kCLLocationAccuracyBest;
[manager startUpdatingLocation];
}
- (void) viewDidLoad {
[super viewDidLoad];
[self loadCurrentLocation];
}
-(void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation {
CLLocation *loc=newLocation;
if (loc!=nil) {
self.latitude=loc.coordinate.latitude; //1
self.longitude=loc.coordinate.longitude; //2
NSLog(#"Gained Latitude:%.f",self.latitude);
NSLog(#"Gained Longitude:%.f",self.longitude);
}
}
Given that latitude and longitude are declared as follows in the .h file:
#interface Prayers :UIViewController<CLLocationManagerDelegate>
#property double longitude;
#property double latitude;
#end
the problem is that the returned values at lines 1 & 2 are integers like 30 and 31 and i was expecting them like 31.377033600000004000 and 30.016893900000000000, so why the returned values are integers instead of double ? thanks in advance
If the types weren't what you expect, Xcode would likely be giving you conversion warnings. What makes you think they aren't doubles you are getting back? Maybe the framework is just rounding to the nearest degree and returning that as a double?
Another possibility. what if your log looked like
NSLog(#"Gained Latitude:%.2f",self.latitude);
Does that print more accuracy (note, the 2 in the format).
Maybe even trying boxing them as an NSNumber and see what that prints:
NSLog(#"Gained Latitude:%#", #(self.latitude));

How to return variable from this method?

I need to return the longitude and latitude from this method. This is from the locationManager code. When I log the lat, longt they give the correct values.
What I have been unable to do is to work out you to export/return the variables out of this method. How should I go about changing it?
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
int degrees = newLocation.coordinate.latitude;
double decimal = fabs(newLocation.coordinate.latitude - degrees);
int minutes = decimal * 60;
double seconds = decimal * 3600 - minutes * 60;
self.lat = [NSString stringWithFormat:#"%d° %d' %1.4f\"", degrees, minutes, seconds];
NSLog(#"Current Latitude : %#",self.lat);
degrees = newLocation.coordinate.longitude;
decimal = fabs(newLocation.coordinate.longitude - degrees);
minutes = decimal * 60;
seconds = decimal * 3600 - minutes * 60;
self.longt = [NSString stringWithFormat:#"%d° %d' %1.4f\"", degrees, minutes, seconds];
NSLog(#"Current Longitude : %#",self.longt);
[manager stopUpdatingLocation];
}
You don't need to return the location from that method because you're not going to call that method yourself -- the Location Manager will call that method to give you an updated location. What you should do is to store the new location so that your code can use it later. Usually, that just means updating your instance variables, but you can do whatever you want with the location -- update you data model, write it out to a text file, etc. Storing it in ivars makes it easy to access the location whenever you need it in your code.

Settings default value to float variable

I'm developing a location based app and I'm using the following code (which works perfectly) to retrieve the location of the user. However, I would like to set a default value to the longitude and latitude in case the user turned off location services.
I tried self.latitude = 0; but the app crashes. latitude and longitude are variables of type float. Ideally I want to set them to a default value of (0,0).
So basically: how can I set a default value for a variable of type float?
Thanks for your help.
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
self.latitude = newLocation.coordinate.latitude;
self.longitude = newLocation.coordinate.longitude;
SVGeocoder *geocodeRequest = [[SVGeocoder alloc] initWithCoordinate:newLocation.coordinate];
[geocodeRequest setDelegate:self];
[geocodeRequest startAsynchronous];
// NSLog(#"lat:%f,long:%f",self.latitude,self.longitude);
[self.locationMgr stopUpdatingLocation];
}

Having trouble calculating accurate total walking/running distance using CLLocationManager

I'm trying to build an iOS app that displays the total distance travelled when running or walking. I've read and re-read all the documentation I can find, but I'm having trouble coming up with something that gives me an accurate total distance.
When compared with Nike+ GPS or RunKeeper, my app consistently reports a shorter distance. They'll report the same at first, but as I keep moving, the values of my app vs other running apps gradually drift.
For example, if I walk .3 kilometers (verified by my car's odometer), Nike+ GPS and RunKeeper both report ~.3 kilometers every time, but my app will report ~.13 kilometers. newLocation.horizontalAccuracy is consistently 5.0 or 10.0.
Here's the code I'm using. Am I missing something obvious? Any thoughts on how I could improve this to get a more accurate reading?
#define kDistanceCalculationInterval 10 // the interval (seconds) at which we calculate the user's distance
#define kNumLocationHistoriesToKeep 5 // the number of locations to store in history so that we can look back at them and determine which is most accurate
#define kValidLocationHistoryDeltaInterval 3 // the maximum valid age in seconds of a location stored in the location history
#define kMinLocationsNeededToUpdateDistance 3 // the number of locations needed in history before we will even update the current distance
#define kRequiredHorizontalAccuracy 40.0f // the required accuracy in meters for a location. anything above this number will be discarded
- (id)init {
if ((self = [super init])) {
if ([CLLocationManager locationServicesEnabled]) {
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
self.locationManager.distanceFilter = 5; // specified in meters
}
self.locationHistory = [NSMutableArray arrayWithCapacity:kNumLocationHistoriesToKeep];
}
return self;
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
// since the oldLocation might be from some previous use of core location, we need to make sure we're getting data from this run
if (oldLocation == nil) return;
BOOL isStaleLocation = [oldLocation.timestamp compare:self.startTimestamp] == NSOrderedAscending;
[self.delegate locationManagerDebugText:[NSString stringWithFormat:#"accuracy: %.2f", newLocation.horizontalAccuracy]];
if (!isStaleLocation && newLocation.horizontalAccuracy >= 0.0f && newLocation.horizontalAccuracy < kRequiredHorizontalAccuracy) {
[self.locationHistory addObject:newLocation];
if ([self.locationHistory count] > kNumLocationHistoriesToKeep) {
[self.locationHistory removeObjectAtIndex:0];
}
BOOL canUpdateDistance = NO;
if ([self.locationHistory count] >= kMinLocationsNeededToUpdateDistance) {
canUpdateDistance = YES;
}
if ([NSDate timeIntervalSinceReferenceDate] - self.lastDistanceCalculation > kDistanceCalculationInterval) {
self.lastDistanceCalculation = [NSDate timeIntervalSinceReferenceDate];
CLLocation *lastLocation = (self.lastRecordedLocation != nil) ? self.lastRecordedLocation : oldLocation;
CLLocation *bestLocation = nil;
CGFloat bestAccuracy = kRequiredHorizontalAccuracy;
for (CLLocation *location in self.locationHistory) {
if ([NSDate timeIntervalSinceReferenceDate] - [location.timestamp timeIntervalSinceReferenceDate] <= kValidLocationHistoryDeltaInterval) {
if (location.horizontalAccuracy < bestAccuracy && location != lastLocation) {
bestAccuracy = location.horizontalAccuracy;
bestLocation = location;
}
}
}
if (bestLocation == nil) bestLocation = newLocation;
CLLocationDistance distance = [bestLocation distanceFromLocation:lastLocation];
if (canUpdateDistance) self.totalDistance += distance;
self.lastRecordedLocation = bestLocation;
}
}
}
As it turns out, the code I posted above works great. The problem happened to be in a different part of my app. I was accidentally converting the distance from meters to miles, instead of from meters to kilometers. Oops!
Anyway, hopefully my post will still have some merit, since I feel it's a pretty solid example of how to track a user's distance with Core Location.
You probably have set kRequiredHorizontalAccuracy too low. If there is no location in the history that has accuracy < kRequiredHorizontalAccuracy, then you ignore all those points and add 0 to the distance.

Why do I get extra location coordinate points when my iPhone app first launches?

I am working an iPhone app which is using CLLocationManager. When a user goes for a run, it shows the run path on a mapView. I am drawing the running path on mapView using following code:
double leastDistanceToRecord = 0.0000905;
- (void) locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
if (newLocation.horizontalAccuracy >= 0) {
if (!runoPath)
{
NSLog(#"in !runoPath if");
// This is the first time we're getting a location update, so create
// the RunoPath and add it to the map.
runoPath = [[RunoPath alloc] initWithCenterCoordinate:newLocation.coordinate];
[map addOverlay:runoPath];
self.currentRunData = [[RunData alloc] init];
[currentRunData startPointLocation:newLocation];
// On the first location update, zoom map to user location
MKCoordinateRegion region =
MKCoordinateRegionMakeWithDistance(newLocation.coordinate, 1000, 1000);
[map setRegion:region animated: NO];
}
else
{
// This is a subsequent location update.
// If the runoPath MKOverlay model object determines that the current location has moved
// far enough from the previous location, use the returned updateRect to redraw just
// the changed area.
double latitudeChange = fabs(newLocation.coordinate.latitude - oldLocation.coordinate.latitude);
double longitudeChange = fabs(newLocation.coordinate.latitude - oldLocation.coordinate.longitude);
if (latitudeChange > leastDistanceToRecord || longitudeChange > leastDistanceToRecord) {
MKMapRect updateRect = [runoPath addCoordinate:newLocation.coordinate];
if (!MKMapRectIsNull(updateRect))
{
// There is a non null update rect.
// Compute the currently visible map zoom scale
MKZoomScale currentZoomScale = map.bounds.size.width / map.visibleMapRect.size.width;
// Find out the line width at this zoom scale and outset the updateRect by that amount
CGFloat lineWidth = MKRoadWidthAtZoomScale(currentZoomScale);
updateRect = MKMapRectInset(updateRect, -lineWidth, -lineWidth);
// Ask the overlay view to update just the changed area.
[runoPathView setNeedsDisplayInMapRect:updateRect];
}
// [currentRunData updateLocation:oldLocation toNewLocation: newLocation];
}
[currentRunData updateLocation:oldLocation toNewLocation: newLocation];
// }
}
}
}
The problem is that when I start a run, I get some extra points and then because of those points I get an extraneous line on mapView that does not reflect the actual run. It even happens when I install the app on my iPhone and run it for the first time. I don't know why it's adding those extra points. Can anyone help me with that? Thanks in advance.
The first location you get is usually a cached location and is old. You can check the age of the location and if it is old (>60 seconds or whatever) then ignore that location update. See this answer here.
--EDIT-- If you are still having problems, put this code in didUpdateToLocation: and show us the actual output from NSLog (you can edit your question and add the output):
NSTimeInterval age = -[newLocation.timestamp timeIntervalSinceNow];
NSLog(#"age: %0.3f sec, lat=%0.2f, lon=%0.2f, hAcc=%1.0f",
age, newLocation.coordinate.latitude, newLocation.coordinate.longitude,
newLocation.horizontalAccuracy);