IOS10 on iPhone 6 Plus.
A small app app that grabs the gps coordinates and sends them to a remote web service. On the iphone map the user location is showing correctly, but the retrieved coordinates:
location.coordinate.latitude,
location.coordinate.longitude
are 0.5 miles away from where the map says I am! This is consistent wherever I move to.
I am following Apple's best practices and using the delegate method as follows: and it's these coordinates that are incorrect.
// Delegate method from the CLLocationManagerDelegate protocol.
- (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations {
CLLocation* location = [locations lastObject];
NSDate* eventDate = location.timestamp;
NSTimeInterval howRecent = [eventDate timeIntervalSinceNow];
if (abs(howRecent) < 15.0) {
// Log the data
NSLog(#"latitude %+.6f, longitude %+.6f\n",
location.coordinate.latitude,
location.coordinate.longitude);
}
}
I am setting the location accuracy as follows:
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
I sample the gps coordinates for 30 seconds to make sure i am getting the best accuracy possible.
I have tried this on 2 different iPhones, both showing the same issue.
Thanks in advance.
I finally found out what is causing the problem..
I am currently in China... and that is the reason for the mysterious offset.. the maps in China are 'offset'.
If you are interested there's an post about it here that has saved me from tearing my hair out.
http://www.sinosplice.com/life/archives/2013/07/16/a-more-complete-ios-solution-to-the-china-gps-offset-problem.
China uses a mapping projection called GCJ-02 which is different from the West's mapping standard (WGS-84). So if you're ever developing a mapping system, you might want to take this into account for travellers in China!
Thanks anyway for the useful pieces of coding advice.
You can add a check in your method to update locations again until you are down to your desired accuracy:
// Delegate method from the CLLocationManagerDelegate protocol.
- (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations {
// You can check for either locationManager.desiredAccuracy or a value you'd like in meters
CLLocation* location = [locations lastObject];
if (location.horizontalAccuracy > locationManager.desiredAccuracy) {
//Do nothing yet
return;
}
NSDate* eventDate = location.timestamp;
NSTimeInterval howRecent = [eventDate timeIntervalSinceNow];
if (abs(howRecent) < 15.0) {
// Log the data
NSLog(#"latitude %+.6f, longitude %+.6f\n",
location.coordinate.latitude,
location.coordinate.longitude);
}
}
Related
I'm doing a query inside of:
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{
if (!gotLocation){
gotLocation = true;
[locationManager stopUpdatingLocation];
// DO QUERY
}
}
But I would like to know when the final location is set, or when a more accurate one is made. I'm trying to query only once and need a precise location for the query. I know I can use [locations lastObject], but how can I determine when the final or a more precise location is set.
You can check the location's horizontalAccuracy. The smaller the value the more accurate. You should hold a reference to the last location you received then when a new location comes in that is more accurate, the horizontalAccuracy is smaller, updated your reference.
Then once you receive a location with a horizontalAccuracy close enough for your use case then you can call stopUpdatingLocation since you have your location, then do your query.
For example:
CLLocation *location = [locations lastObject];
if (location.horizontalAccuracy < self.lastLocation.horizontalAccuracy) {
self.lastLocation = location;
if (self.lastLocation.horizontalAccuracy <= kDesiredLocationAccuracy) {
// execute query or additional logic
[locationManager stopUpdatingLocation];
}
}
Hope that helps!
I m using location delegate methods to get the current location of the user.Everything is working fine when i debug it using xcode 7.3 but when I debug it using latest Xcode 8 and turn off location service from settings,in that case the pop up of location service disable and pop up to ask permission to get the location continuously appears on the screen and it freezes the app screen until the phone is restarted.
This is the code in AppDelegate class
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{
NSLog(#"locationManager didUpdateLocations: %#",locations);
for(int i=0;i<locations.count;i++){
CLLocation * newLocation = [locations objectAtIndex:i];
CLLocationCoordinate2D theLocation = newLocation.coordinate;
CLLocationAccuracy theAccuracy = newLocation.horizontalAccuracy;
self.myLocation = theLocation;
self.myLocationAccuracy = theAccuracy;
}
if (self.shareModel.afterResume==TRUE) {
appStatus=#"Killed";
self.locationTracker = [[LocationTracker alloc]init];
self.locationTracker.str_latitude=[NSString stringWithFormat:#"%f",self.myLocation.latitude];
self.locationTracker.str_longitude=[NSString stringWithFormat:#"%f",self.myLocation.longitude];
self.locationTracker.pushStatus=FALSE;
[self.locationTracker GetDevice_LocationSettings];
}
}
These two pop up comes one after another and doesn't allow to do any other action.
I want the current latitude and longitude of my device. I can print latitude and longitude when my program locate the device for the first time but I can't refresh it.
-(void) locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
int lastindex = [locations count]-1;
CLLocation * currentLocation = [locations objectAtIndex:lastindex];
float latitude =currentLocation.coordinate.latitude;
float longitude =currentLocation.coordinate.longitude;
NSLog(#"LAT:%f LONG:%f",latitude,longitude);
[self latitudeLabel].text = [[NSString alloc]initWithFormat:#"latitude : %#",[[NSNumber numberWithFloat:latitude] stringValue]];
[self longitudeLabel].text = [[NSString alloc]initWithFormat:#"longitude : %#",[[NSNumber numberWithFloat:longitude] stringValue]];
}
This is what I tried but latitude/longitude are never updated. I tried it with the function didUpdateHeading but that didn't work either.
How can i do this. Any one can help me to solve this issue.
Thanks you
This method is triggered by startUpdatingLocation which I assume you're using since it did get called at least once. The method gets called each time the location data changes. Is your location actually changing enough to trigger it? Also, check the distanceFilter property on your CLLocationManager and make sure it is low enough.
Make sure you add the following to your header:
#interface YourLocationObject : SomeObject <CLLocationManagerDelegate>
.. and when you create your CLLocationManager object, you set yourself as the delegate:
CLLocationManager *locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
//... other customization here ...//
[locationManager startUpdatingLocations];
I'm trying to develop an Altimeter on Xcode and Simulator but it always return 0 for the height above the sea.
I don't understand why, I've tried with a lot of places on Simulator.
My code is this:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
_mapView.delegate = self;
_locationManager = [[CLLocationManager alloc] init];
_locationManager.desiredAccuracy = kCLLocationAccuracyBest;
_locationManager.pausesLocationUpdatesAutomatically = YES;
_locationManager.delegate = self;
firstLocation = YES;
checkUserLocation = NO;
}
- (void) locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{
CLLocation *location = [locations lastObject];
lastLocation = location.coordinate;
_latitudeLabel.text = [NSString stringWithFormat:#"Current latitude: %f", location.coordinate.latitude];
_longitudeLabel.text = [NSString stringWithFormat:#"Current longitude: %f", location.coordinate.longitude];
_altitudeLabel.text = [NSString stringWithFormat:#"Current altitude: %f m", location.altitude];
}
Where is my error?
There's nothing wrong with your code, its because you are using the simulator.
Determining altitude requires a device with GPS capabilities, and you also need to be using GPS on that device in order to get it (wifi only location would not report altitude correctly even on GPS-enabled devices). The iOS simulator does not have those capabilities so altitude will not be accurate there. You will need to use a real device with GPS to get altitude measurements.
If you want to simulate a CLLocation with altitude you can create your CLLocation object and pass it an altitude yourself:
- (id)initWithCoordinate:(CLLocationCoordinate2D)coordinate
altitude:(CLLocationDistance)altitude
horizontalAccuracy:(CLLocationAccuracy)hAccuracy
verticalAccuracy:(CLLocationAccuracy)vAccuracy
timestamp:(NSDate *)timestamp
Altitude is a readonly property so you will need to create a new CLLocation object yourself instead of changing it manually when you receive a CLLocation object in your delegate callback.
In my app(Deployment Target 5.1), i am using CoreLocation to setup a reminder feature, it will basically search the nearby items(have location attached) as device update its current location.
This feature is not working very stable at this stage, sometimes it just doesn't works at all regardless of whether device is in active, suspended and terminated states. i realized that the delegate method locationManager:didUpdateToLocation:fromLocation: didn't get call.
Is there anybody can point me a direction to make this thing work properly?
Here is my setup for the CLLocationManager
sharedLocationManager = [[CLLocationManager alloc]init];
[ESLocationManager defaultManager].delegate = someDelegateClassInstance;
[[ESLocationManager defaultManager] setDesiredAccuracy:kCLLocationAccuracyHundredMeters];
[[ESLocationManager defaultManager] startMonitoringSignificantLocationChanges];
And the implementation of the delegate callback
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
// If it's a relatively recent event, turn off updates to save power
NSDate* eventDate = newLocation.timestamp;
NSTimeInterval howRecent = [eventDate timeIntervalSinceNow];
if (abs(howRecent) < 20.0) {
// If the event is recent,find nearby items.
NSLog(#"latitude %+.6f, longitude %+.6f\n",
newLocation.coordinate.latitude,
newLocation.coordinate.longitude);
//reload nearby list
NSArray *nearbyItems = [self nearbyItemsForLocation:newLocation];
if (nearbyItems && nearbyItems.count ) {
UIApplicationState appState = [[UIApplication sharedApplication] applicationState];
if (appState != UIApplicationStateActive) {
[[UIApplication sharedApplication] presentLocalNotificationNow:[self localNotificationForItems:nearbyItems]];
}
}
}
}
Similar reason to this forum with region monitoring
https://devforums.apple.com/message/251046#251046
Hope this helps