I want to show user's current location with iphone gps feature but problem is it is giving incorrect location .
When i drop pin on map then it drops pin at exact position but when i try to see the location in text then it gives inaccurate location with inaccuracy of 500 to 800 meters approx.I have used reverse geocoding and google api but all giving same location. PLease tell me why this happens and how can i show the exact location of user ?
My code is:
cllocationmanager *locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.distanceFilter = kCLDistanceFilterNone; // whenever we move
locationManager.desiredAccuracy = kCLLocationAccuracyBest; // 100 m
[locationManager startUpdatingLocation];
}
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
CLLocationCoordinate2D here = newLocation.coordinate;
NSLog(#"%f %f ", here.latitude, here.longitude);
MKReverseGeocoder *geocoder = [[MKReverseGeocoder alloc] initWithCoordinate:here];
[geocoder setDelegate:self];
[geocoder start];
}
- (void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFailWithError:(NSError *)error{
}
- (void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFindPlacemark:(MKPlacemark *)placemark
{
NSLog(#"The geocoder has returned: %#", [placemark addressDictionary]);
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Error" message:[NSString stringWithFormat:#"%#",[placemark addressDictionary]] delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alertView show];
[alertView release];
}
Quick guess: did you check the CLLocation's horizontal accuracy? Quite often the first response I get is very inaccurate, and then subsequent calls get better.
Edit: #pankaj First of all, can you confirm that it is an accuracy issue. If it is the problem that I'm suggesting, then the CLLocation horizontalAccuracy will be large. If not the case then you can ignore my answer and these comments. However, if horizontalAccuracy is a large error then you will have to wait for a better lock. There are two ways to do this:
Wait for a short period of time (a second or two) and see if you get a better lock.
Start requesting location much earlier on, e.g. when the app launches, or when the UIViewController that requires location starts.
Related
I need to get user location and fetch latitude and longitude of even when there is no internet available.
Right now i have implemented CoreLocation methods:-
-(void)updatestart
{
// Current location
_locationManager = [[CLLocationManager alloc]init];
_locationManager.desiredAccuracy = kCLLocationAccuracyBest;
_locationManager.delegate = self;
[_locationManager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
NSLog(#"didFailWithError: %#", error);
UIAlertView *errorAlert = [[UIAlertView alloc]
initWithTitle:#"Error" message:#"Failed to Get Your Location" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[errorAlert show];
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation{
[_locationManager stopUpdatingLocation];
NSLog(#"%f",_locationManager.location.coordinate.latitude);
NSLog(#"%f",_locationManager.location.coordinate.longitude);
}
and i am getting the location updates but this only works if we have internet connection.
I guess using iPhone GPS we can fetch the location even without internet.
Any idea of how to implement that??
Thanks in advance.
GPS doesn't need data exchange using internet, but it has basically 2 disadvantages:
it takes a long time to get position if you haven't used it recently (this is
due to satellite search)
it doesn't work inside buildings or where streets are too small
between buildings (this happens a lot in Italy)
Another way that it doesn't need data exchange is location based on cell tower, but of course your device should have cellular chip installed.
From your code I see three things that should be fixed as soon as possible.
Sometimes the first location is cached and it doesn't represent the
actual location
It will be better to stop the location manager when you receive a
valid coordinate, that means: not cached, with an horizontal accuracy >=0 and with an horizontal accuracy that match your requirements,
The delegate methods to get location is deprecated (depending on your
deployment target). Here is a little snippet for the first two
points:
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{
CLLocation * newLocation = [locations lastObject];
if (newLocation.horizontalAccuracy < 0) {
return;
}
NSTimeInterval interval = [newLocation.timestamp timeIntervalSinceNow];
if (abs(interval)>20) {
return;
}
}
I am trying to calculate distance from start using Core Location framework, but when i put the Application on an iPhone device, the data is not correct. Distance keeps on fluctuating and showing random data. Kindly help me out. Also, Altitude is showing zero.
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
//Altitude
if(startingPoint==nil)
self.startingPoint=newLocation;
NSString *currentAltitude = [[NSString alloc] initWithFormat:#"%g",
newLocation.altitude];
heightMesurement.text=currentAltitude;
[currentAltitude release];
//Distance
if(startingPoint==nil)
self.startingPoint=newLocation;
//if(newLocation.horizontalAccuracy <= 100.0f) {
// [locationManager stopUpdatingLocation];
//}
//test start.......................................................
//startlocation
NSString *sp = [[NSString alloc]
initWithFormat:#"%f",startingPoint];
NSLog(#"\nStarting point=%#",startingPoint);
ssp.text=sp;
//endlocation
NSString *ep = [[NSString alloc]
initWithFormat:#"%f",newLocation];
NSLog(#"\nStarting point=%#",newLocation);
eep.text=ep;
//test end............................................................
CLLocationDistance mydistance=[newLocation distanceFromLocation:startingPoint];
NSString *tripString = [[NSString alloc]
initWithFormat:#"%f",mydistance];
distLabel.text=tripString;
[tripString release];
//test........................
[sp release];
[ep release];
}//Location Manager ends..
//Time interval of 3 sec....
-(void)locationUpdate:(NSTimer*)timer{
if(timer != nil) [timer invalidate];
[self.locationManager startUpdatingLocation];
}
As to why your altitude may be zero, please see this answer to a similar question.
This may just be a problem with your NSLog statements, but both the starting and ending points are printed out with NSLog statements that say
NSLog(#"\nStarting point=%#",
The way you seem to have scheduled a 3-second timer is not really the way iOS wants you to use CLLocationManager. The preferred way is to tell CLLocationManager what your location criterion are, and then just start it updating. You don't actually need to keep telling it to start updating every 3 seconds. You can just do it once, and then if you ever decide you don't need any more updates, then call
[locationManager stopUpdatingLocation];
If the OS has no new location information, it probably doesn't make sense to keep asking. It'll tell you when it has new location information, via locationManager:didUpdateToLocation:fromLocation. So, I would recommend starting the process more like this:
CLLocationManager* locationManager = [[CLLocationManager alloc] init];
if ([locationManager locationServicesEnabled]) {
Reachability* netStatus = [Reachability sharedReachability];
if (([netStatus internetConnectionStatus] != NotReachable) || ([netStatus localWiFiConnectionStatus] != NotReachable)) {
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
locationManager.distanceFilter = 100.0; // 100 m, or whatever you want
[locationManager startUpdatingLocation];
} else {
// TODO: error handling
}
}
self.locMgr = locationManager;
[locationManager release];
The location manager will often deliver you multiple results, with increasing accuracy as it hones in on your location. If you're continually restarting it, I'm wondering if that's causing it problems.
Background: I want to allow users to get their location within seconds when they want it. However, the location is mostly inaccurate. I want to ask the user to if they would like to try again for a more accurate address.
Question: How to code such that it guarantees that the next guess, is always better than the last guess.
What I have tried:
CLLocationManager *locationManager;
- (CLLocationManager *)locationManager {
if (locationManager != nil) {
return locationManager;
}
locationManager = [[CLLocationManager alloc] init];
[locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
[locationManager setDelegate:self];
return locationManager;
}
-(void)myLocationClickedWithCount: (int) count{
[[self locationManager] startUpdatingLocation];
CLLocation *location = [locationManager location];
CLGeocoder *locationGeocoded = [[CLGeocoder alloc] init];
[locationGeocoded reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks, NSError *error) {
CLPlacemark *placemark = [placemarks objectAtIndex:0];
if (!placemark){
if (count > 0){
//placemark not available, try again after 1 second
sleep(1);
[self myLocationClickedWithCount:count-1];
}
else{
//Unable to get location after 3 tries
UIAlertView *locationNotFoundAlert = [[UIAlertView alloc]initWithTitle:#"Unable to Locate" message:#"Would you like to try again?" delegate:self cancelButtonTitle:#"No" otherButtonTitles:#"Yes", nil];
locationNotFoundAlert.tag = locationNotFoundAlertTag;
[locationNotFoundAlert show];
}
}else{
// got location but not accurate.
if (location.horizontalAccuracy > accuracyRadius) {
UIAlertView *locationInaccurateAlert = [[UIAlertView alloc]initWithTitle:#"Inaccurate Location" message:[NSString stringWithFormat:#"Your GPS shows the radius of %.2f meters. Would you like to try again?",location.horizontalAccuracy] delegate:self cancelButtonTitle:#"No" otherButtonTitles:#"Yes", nil];
locationInaccurateAlert.tag = locationInaccurateAlertTag;
[locationInaccurateAlert show];
}else {
address.text = placemark;
}
}
}];
}
Update
When the user asks again, it can take a little longer to guess. I just want to know how I should code it. IE: Should I call [[self locationManager] startUpdatingLocation]; again? or will that reset my location so far. Hence, how can i improve my guess the second time based on the current information GPS has (the longer GPS is on, the better accuracy right?).
there is nothing much you can do regarding accuracy via code... apart from
[locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
which you have already done...
As far as I have seen if you are on 3G or EDGE than your accuracy increases considerably (accuracy level of 5-10m can be achieved).
you can refer this article by Apple which talks how the iphone GPS accuracy works...
hoping this helps..
I have a CLLocation manager called "myLocation".
myLocation = [[CLLocationManager alloc] init];
myLocation.desiredAccuracy = kCLLocationAccuracyBestForNavigation ;
myLocation.distanceFilter = 10 ;
myLocation.delegate=self;
locationEnabledBool = [CLLocationManager locationServicesEnabled];
if (locationEnabledBool ==NO || ( [CLLocationManager authorizationStatus] == kCLAuthorizationStatusDenied)) {
// LocationText.text = #"Location Service Disabled ";
UIAlertView *locationAlert = [[UIAlertView alloc] initWithTitle:#"Location Service Disabled"
message:#"To re-enable, please go to Settings and turn on Location Service for this app."
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[locationAlert show];
[locationAlert release];
}
[myLocation startUpdatingLocation];
and location update function is
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
NSLog(#"old location is %f, %f ", oldLocation.coordinate.latitude, oldLocation.coordinate.longitude);
NSLog(#"new location is %f,%f",newLocation.coordinate.latitude, newLocation.coordinate.longitude );
}
Is there a way to find frequency of location manager update, and If it can be increased or decreased?
Your location update starts only when you call the method [locationManager startUpdatingLocation].
You can control the frequency of the update using an NSTimer. Call the startUpdatingLocation method at regular intervals whenever you need a location update and then immediately call the stopUpdatingLocation method. The next time you will get a location update only at the interval you have set in the NSTimer.
For detecting even the slightest of movements, you need to set
myLocation.distanceFilter = kCLDistanceFilterNone ;
But, please keep in mind,letting location manager to generate updates for even the slightest of movements can end up in lot of battery usage.
This is my first question in this site.
I have this serious problem.... I'll explain this from the beginning…
in my app i need to get the current location of the user when the user click on the button in the application.. but the problem is when is click on the button its not updating to the current location its getting the previous location. But when i reset the location warnings in the iphone app its get the correct location.
Here is the code steps i did for this application to get the current location of the user...
First I import to the application ...
then i am using global files to keep data of the application because i need to access them through the application.
so what I did in the globle.m and .h file is ...
CLLocationManager* locationManager;
#synthesize locationManager
+ (Globals*)sharedGlobals {
#synchronized(self) {
if(_sharedGlobals == nil) {
_sharedGlobals = [[super allocWithZone:NULL] init];
_sharedGlobals.locationManager = [[CLLocationManager alloc]init];
[_sharedGlobals.locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
}
}
return _sharedGlobals;
}
Then in my other view controller I put the CLLocationManagerDelegate and in the .m file
-(IBAction) didTapSearchbtn{
if (![CLLocationManager locationServicesEnabled]) {
}else {
[[Globals sharedGlobals].geoLocations removeAllObjects];
search.text = nil;
[Globals sharedGlobals].fromTextField = NO;
[[Globals sharedGlobals].locationManager setDelegate:self];
[[Globals sharedGlobals].locationManager startUpdatingLocation];
}
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
if (newLocation.horizontalAccuracy < 0) return;
[[Globals sharedGlobals].locationManager setDelegate:nil];
[[Globals sharedGlobals].locationManager stopUpdatingLocation];
[[Globals sharedGlobals].geoLocations setObject:[[NSString alloc] initWithFormat:#"%f", newLocation.coordinate.latitude] forKey:#"geolat"];
[[Globals sharedGlobals].geoLocations setObject:[[NSString alloc] initWithFormat:#"%f", newLocation.coordinate.longitude] forKey:#"geolong"];
[self retriveDataFromInternet];
[[Globals sharedGlobals].locationManager release];
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
//GPS error
[[Globals sharedGlobals].locationManager setDelegate:nil];
[[Globals sharedGlobals].locationManager stopUpdatingLocation];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(#"YumTable!", nil) message:NSLocalizedString(#"Enable Your GPS settings to get your current location", nil) delegate:nil cancelButtonTitle:NSLocalizedString(#"Ok", nil) otherButtonTitles:nil];
[alert show];
[alert release];
[[Globals sharedGlobals].locationManager release];
}
i put the label to my view controller and went different places to take latitudes and longitudes .. but always it getting same latitude and longitude ... but when I reset the location warnings and run the app again it took the correct latitude and longitude ... so if i need to take current location always i have to reset it. But what i need is to get current location every time when i click the search button...
Can any one can say whats wrong in this code and can any one help me ....
And Also very very sorry about my bad english ... :)
The LocationManager will return the previos location because it tries to be as fast as possible and it thinks that this location might be good enough. I usually check the timestamp on the new location to ensure that it is a fresh one. If it is to old I don't stop the manager and wait for the next one.
I would suggest that you look at the sample code provided by Apple, https://developer.apple.com/library/ios/#samplecode/LocateMe/Introduction/Intro.html#//apple_ref/doc/uid/DTS40007801
This code is copied from the example:
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
// test the age of the location measurement to determine if the measurement is cached
// in most cases you will not want to rely on cached measurements
NSTimeInterval locationAge = -[newLocation.timestamp timeIntervalSinceNow];
if (locationAge > 5.0) return;
}
I missed Typed my code ... after I figur that out my application start to work perfectly ... Thank you guys for your great help..
[_sharedGlobals.locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
instead of that I used
[_sharedGlobals.locationManager setDesiredAccuracy:kCLLocationAccuracyBestforNavigation];