Sometimes I receive the wrong value for my current location, an error of up to 2 miles. Am I doing everything correctly?
self.myLocation = [[CLLocationManager alloc] init];
myLocation.delegate = self;
myLocation.desiredAccuracy = kCLLocationAccuracyBest;
[myLocation startUpdatingLocation];
What's the most accurate method to receive GPS location?
You get a stream of location updates from the device when you start monitoring location change and so you need to consider both the timestamp of the location update and its horizontal accuracy.
Use the timestamp to reject old values (for example when you first start monitoring, you will be sent an accurate (at the time) but old cached value).
Use the horizontal accuracy to reject values that are outside of your desired range.
Related
I am making an application which tracks the user. I have notice when the application goes in the background and then when you open the app it's shows the wrong current location for the user until about 5 seconds. Is there to fix that because that 5 seconds delay ruins the tracking results ( it's adds three extra miles for no reason ).
Edit: The issue wasn't actually a "bug". I have to set in my Info.plist that I want background pocessing and boom the application tracking is super Accurate. A little tutorial to do that:
Go to Info.plist
Add an New Row called "Required background modes"
Then add again a new row called "App registers for location updates"
We are Done :)
One thing you can do is check the horizontalAccuracy property on the CLLocation that you're being returned. If this is above a certain threshold then you could throw away the result and wait for a more accurate one. If it is a number of miles out then I would expect the accuracy figure to be quite large. It's most likely using a cell site to determine location rather than GPS, and the margin of error would be much greater.
In your CLLocationManagerDelegate's locationManager:didUpdateLocations: method you could do the following:
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
if ([locations count] > 0) {
CLLocation *lastUpdatedLocation = [locations lastObject];
CLLocationAccuracy desiredAccuracy = 1000; // 1km accuracy
if (lastUpdatedLocation.horizontalAccuracy > desiredAccuracy) {
// This location is inaccurate. Throw it away and wait for the next call to the delegate.
return;
}
// This is where you do something with your location that's accurate enough.
}
}
I have a scenario where i search for the current location.Once the current location search begins i use "startMonitoringSignificantLocationChanges" i get didUpdateToLocation delegate called and i get a location value.
After the search is over i use "stopMonitoringSignificantLocationChanges" to turn off the GPS.
My problem is i may to the surrent location search after some time,when its done that is when i again start searching for current location after sometime GPS turns on but "didUpdateToLocation" is not called.
I am doing all these in a view controller.
I have initialized the location manager and have set the desiredAccuracy to "kCLLocationAccuracyNearestTenMeters" and distanceFilter to "10.0f".
Why i am not able to call "didUpdateToLocation" delegate on stooping the location updates and starting it again.
Please any body help me...
Expecting for a positive response from any of you.
Thank you.
You should use startUpdatingLocation instead of startMonitoringSignificantLocationChanges. startMonitoringSignificantLocationChanges calls didUpdateToLocation only when location is significantly changed.
if (locationManager == nill)
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters;
locationManager.distanceFilter = 10;
[locationManager startUpdatingLocation];
Silly question !! Though I want to know that is it possible that CLLocationManager works without Internet ?????
i.e. iPhone is not connected to internet at all
iPhoneiPadDev's answer is slightly wrong: whilst sometimes the location manager will fail, it can work without network connectivity. If you want to see this for yourself, go for a drive somewhere with terrible or nonexistent cellular reception: GPS will still work.
It very much depends on the environmental conditions around you, and the device you're using. iPod Touches and some iPads don't have GPS, and rely on WiFi hotspots to determine their location data. If you don't have network access the CLLocationManager will return an invalid location.
iPhones and 3G iPads do have GPS, so you may get an appropriate location returned. However, they use A-GPS (assisted GPS), which uses information from the network to allow a faster GPS lock. If you don't have internet connectivity it may take some time for the GPS chip to obtain a signal and provide an accurate location: and accuracy may be wildly off, if you're indoors or don't have plain sight of the sky.
Important point: CLLocationManager can and will return you locations even if none are available: the coordinates, however, will be invalid. It's important to test the locations being returned and make sure you're satisfied they are correct before using them.
Yeah it works if Location Services are enabled in the device settings. No need for Internet connection.
Yes but in open sky(Means on road, ground).
If you are online, you will get location coordinate from wifi, mobile data then if you switch off internet and change your location(Away from that location), Say you are now in building(3rd floor) then you won't get correct location update instead you will get cache coordinates.
To fix this:
Record timestamp(Say "RecordDate") in offline mode when you want location then compare timestamp given by didUpdateToLocations: method.
if didUpdateToLocations's timestamp > Recorded Timestamp then use it
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(nonnull NSArray<CLLocation *> *)locations
{
CLLocation *currentLocation = [locations lastObject];
NSLog(#"didUpdateToLocation: %#", currentLocation);
NSDate *eventDate=[[NSUserDefaults standardUserDefaults] objectForKey:#"RecordDate"];
NSComparisonResult result = [currentLocation.timestamp compare:eventDate];
NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setDateFormat:#"yyyy-MM-dd HH:mm:ss z"];
switch (result)
{
case NSOrderedAscending: {
NSLog(#"Location%# is greater than %#", [df stringFromDate:eventDate], [df stringFromDate:currentLocation.timestamp]);
}
break;
case NSOrderedDescending:
NSLog(#"%# is less %#", [df stringFromDate:eventDate], [df stringFromDate:currentLocation.timestamp]);
if (currentLocation != nil)
{
//Use them
//currentLocation.coordinate.latitude
// currentLocation.coordinate.longitude
}
break;
case NSOrderedSame:
//Use them
break;
default:
NSLog(#"erorr dates %#, %#", [df stringFromDate:eventDate], [df stringFromDate:currentLocation.timestamp]);
break;
}
}
Core Location uses a number of sensors to get a location: Bluetooth, Wi-Fi, GPS, barometer, magnetometer, and what Apple calls "cellular hardware". GPS, BLE, barometer, and magnetometer all don't need a data connection.
time to time there is an issue with geting the location coordinate on my app.
I have been testing my app for location coordinate from the simulator and the iphone sitting at my home (it is not just my home, i tested it in different location (outdoor) as well with a very good network connectivity), and i see this wired behavior, i have the right co ordinate at the moment and then i send the app to the background and bring it back i get the right location co ordinate, and if i do it 8-10 times (i.e sending it to background and bringing it to foreground) once in a while after the app comes from the background i cannot get location co ordinate, the only way to get the location co ordinate at this moment is to kill the app and then start fresh. So i am sure some thing is going wrong but I am not sure what is it.
This is what I am doing
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
//if the time interval returned from core location is more than 30 seconds we ignore it because it might be from an old session
if ( abs([newLocation.timestamp timeIntervalSinceDate: [NSDate date]]) < 30) {
if(newLocation.coordinate.latitude != previousLocation.coordinate.latitude && newLocation.coordinate.longitude != previousLocation.coordinate.longitude){
if(newLocation.horizontalAccuracy <= 100){
[self.locationManager stopUpdatingLocation];
[self.locationManager startMonitoringSignificantLocationChanges];
}
else{
[self.locationManager startUpdatingLocation];
}
So basically i take the newLocation only if it is not older then 30 sec, and it is not same as previous location that i have stored locally and the horizontal accuracy is less than 100 meter. When i run it in debugger what i am observing is i get to the first if condition 3-4 times and if it fails it doesn't come after that, which means didUpdateToLocation doesn't get called at all.
Once the co ordinate meet all my criteria I do stopupdatinglocation and do startMonitoringSignificantLocationChanges.
The reason i am doing startUpdatingLocation in my else block is.
For example if didUpdateToLocation got called due to the startMonitoringSignificantLocationChanges, i want to get the accurate location after that so i am doing startUpdatingLocation every time i don't get the right location that i am looking for as i believe doing multiple startUpdatingLocation doesn't harm anything.
Let me know if there is something wrong in my thought process or in the code logic.
The first thing I would check is your info.plist. You have to include the key Required Background Modes -> App registers for location updates. Without this you won't receive location updates (besides significant location changes and region monitoring) while in the background.
In the main else, you call startUpdatingLocation. While I don't believe this hurts anything, unless you are balancing it with a stopUpdatingLocation I don't believe it will do anything. Documentation says:
Calling this method several times in succession does not automatically result in new events being generated. Calling stopUpdatingLocation in between, however, does cause a new initial event to be sent the next time you call this met
But either way, I don't think you need to tell it to startUpdating again, it will continue on it's own when the distanceFilter property is exceeded or the hardware gathers a more accurate location reading.
I don't see a closing } for your second if.
I'm not using this for driving directions or similar. I have a few annotations and want a trigger when user is in the vicinity of one of those, so I can alert the user.
It seems didUpdateToLocation is called only once per startUpdatingLocation call? At least when I NSLog within that method, I only get one line in console. No, I'm not walking around with the iphone.
So: What is the correct way to set up a continuous monitoring of userLocation and get a "callback" (either when 3-4 seconds have passed or when user has moved say, 10 meters)?
As you probably know, this is the code to initialize and start the location manager:
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.distanceFilter = kCLDistanceFilterNone;
locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters;
[locationManager startUpdatingLocation];
And implement didUpdateToLocation like this:
- (void) locationManager:(CLLocationManager*)manager didUpdateToLocation:(CLLocation*)newLocation fromLocation:(CLLocation*) oldLocation
{
// This will be called every time the device has any new location information.
}
The system will call didUpdateToLocation every time there is an update to the location. If the system does not detect a change in location didUpdateToLocation will not be called. The only thing you can do is to set the distanceFilter and desiredAccuracy like i did in the example to give you the highest accuracy.
Update
Use kCLLocationAccuracyBest instead of kCLLocationAccuracyNearestTenMeters for more accuracy.