I have searched a lot and didn't get any satisfactory answer, I have a scenario where I am showing a list of sellers based on user's current location. I am getting a location for the first time and when I run my App afterward whenever I try to get the location I am getting a cache location data. I did try after some time even after every 24 hours but still getting the cache location where my current location is changed as well. Following is the code I am using for reference. please advise.
Property defined in Header file
#property (nonatomic,retain) CLLocationManager *locationManager;
- (void)startSingleLocationRequest
{
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
self.locationManager.distanceFilter = kCLDistanceFilterNone;
self.locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters;
[self.locationManager startUpdatingLocation];
[self.locationManager requestWhenInUseAuthorization];
}
#pragma mark --didUpdateLocations
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations{
self.latitudeValue = locations.lastObject.coordinate.latitude;
self.longitudeValue = locations.lastObject.coordinate.longitude;
// location set for simulation to UK
if(self.latitudeValue != 51.509979 && self.longitudeValue != -0.133700){
[MBProgressHUD hideHUDForView:self.outletSearchNearBy animated:YES];
[self.locationManager stopUpdatingLocation];
abc *slv =[self.storyboard instantiateViewControllerWithIdentifier:#"abc"];
slv.receivedLatitudeValue = self.latitudeValue;
slv.receivedLongitudeValue = self.longitudeValue;
[self.navigationController pushViewController:slv animated:YES];
}
else{}
}
You can do something like,
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{
for(int i=0;i<locations.count;i++){
CLLocation * newLocation = [locations objectAtIndex:i];
CLLocationCoordinate2D theLocation = newLocation.coordinate;
CLLocationAccuracy theAccuracy = newLocation.horizontalAccuracy;
NSTimeInterval locationAge = -[newLocation.timestamp timeIntervalSinceNow];
if (locationAge > 5.0)
{
continue;
}
// do your all stuff here and then
break;
}
}
Your code will not executes if your location age is more than 5 seconds. You can decide location age lie 10 seconds or 20 seconds!
Update :
Just replace your property declaration
#property (nonatomic,retain) CLLocationManager *locationManager;
with
#property (nonatomic,strong) CLLocationManager *locationManager;
or
just declare it as instance variable like,
CLLocationManager *locationManager;
and remove self from avery instance of it!
Second thing,
You should do first,
[self.locationManager requestWhenInUseAuthorization];
and then start update of location,
[self.locationManager startUpdatingLocation];
Can you try like this
self.locationManager.pausesLocationUpdatesAutomatically = NO;
Because it
Specifies that location updates may automatically be paused when possible.
By default, this is YES for applications linked against iOS 6.0 or later.
On the other hand, kCLLocationAccuracyBestForNavigation uses top speed GPS. So better to use this instead of kCLLocationAccuracyNearestTenMeters.
Lion thanks for the support, actually i was checking location inside the plaza and due to that i was not getting the right location, i tested by coming outside and it is showing perfectly. anyways thanks lion you have been really helpful.
Related
Using iOS 8 and have NSLocationAlwaysUsageDescription set.
Here is my code:
#import "GeoLocation.h"
#import "AppDelegate.h"
#implementation GeoLocation
- (id)init
{
self = [super init];
if (self)
{
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
self.locationManager.distanceFilter = 5; //in meters
// Check for iOS 8. Without this guard the code will crash with "unknown selector" on iOS 7.
if ([self.locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)]) {
[self.locationManager requestWhenInUseAuthorization];
}
self.numberOfUpdates = 0;
[self.locationManager startUpdatingLocation];
}
return self;
}
// Wait for location callbacks
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
NSLog(#"Location Updated: %#", [locations lastObject]);
}
- (float) getLatitude
{
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSLog(#"getLatitude: %f", self.locationManager.location.coordinate.latitude);
appDelegate.gMyProfile.latitude = self.locationManager.location.coordinate.latitude;
return self.locationManager.location.coordinate.latitude;
}
- (float) getLongitude
{
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSLog(#"getLongitude: %f", self.locationManager.location.coordinate.longitude);
appDelegate.gMyProfile.longitude = self.locationManager.location.coordinate.longitude;
return self.locationManager.location.coordinate.longitude;
}
- (float) getAltitude
{
return self.locationManager.location.altitude;
}
When the user logs in, I instantiate a GeoLocation object, which turn on starts updating the location.
If I use
self.locationManager.distanceFilter = 5;
and walk around my house, didUpdateLocations won't fire.
However, if I get rid of
self.locationManager.distanceFilter = 5;
didUpdateLocations will fire every second.
Anything you guys see that I am not. I would love for this to update when the user moves 5 meters.
Adding a distance filter will most likely cause iOS to take the horizontalAccuracy into account.
Since you are inside you will be unlikely to get location with a horizontalAccuracy of 5 which is the best accuracy.
Without the distance filter you are probably just getting the same location or another location within the distance in horizontalAccuracy.
Generally you will only get an accuracy of 5m meters when you are outside in clear view of the satellites above you and not next to tall buildings that can reflect and obscure the signal.
I'm trying to getting my current location exact according to my coordinates. I've implemented CLLocationManager in my viewController called myLocation.
My problem is, I'm getting not getting my co-ordinates for the first time, but when I again approach I got the coordinates. I'm unable to understand this problem that why this not appear for the first time.
I also tried to give a NSTimer to stoplocation but but still unable to get the result for the first time, every first time I getting a (null) value, and then getting the co-ordinates.
My Code:
#import <UIKit/UIKit.h>
#import <Corelocation/CoreLocation.h>
#interface myLocation : UITableViewController<CLLocationManagerDelegate>
#property (strong, nonatomic) CLLocationManager *locationManager;
#end
#interface myLocation () {
CLLocationManager* _locationManager;
NSString * _lat;
NSString * _lng;
}
#end
#implementation myLocation
- (void)viewDidLoad
{
[super viewDidLoad];
_locationManager = [[CLLocationManager alloc] init];
_locationManager.distanceFilter = kCLDistanceFilterNone;
_locationManager.delegate = self;
_locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters;
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
[_locationManager requestWhenInUseAuthorization];
[_locationManager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations {
CLLocation *location = [locations lastObject];
[_locationManager stopUpdatingLocation];
_lat =[NSString stringWithFormat:#"%f",location.coordinate.latitude];
_lng =[NSString stringWithFormat:#"%f",location.coordinate.longitude];
}
- (void)viewWillAppear:(BOOL) animated
{
NSLOG(#"%#",_lat);
NSLOG(#"%#",_lng);
}
Your coordinates aren't appearing yet when you attempt to print them in viewWillAppear: because the CLLocationManager hasn't had enough time to retrieve the first location yet. Wait until didUpdateLocations: is first called before attempting to utilize the device coordinates because didUpdateLocations: is where you'll be receiving those coordinates. I recommend deleting your attempt to print the coordinates code from your viewWillAppear and simply print them in didUpdateLocations: instead.
In the comments, the OP stated he wants to "refresh" the location during viewWillAppear. I suggest stopping the updates when the view disappears and restarting the updates as soon as the view reappears:
- (void)viewWillAppear:(BOOL) animated
{
[_locationManager startUpdatingLocation];
}
- (void)viewWillDisappear:(BOOL) animated
{
[_locationManager stopUpdatingLocation];
}
It takes some time for location services to start up and call your delegate method - This almost certainly won't happen before viewWillAppear is called if you are only starting location services in viewDidLoad. Also, the first time your app executes it has to wait for the user to grant permission.
You can examine the location property of your CLLocationManager to get the most recent location. If it is nil then no location has been determined (yet).
I have IBAction:
-(IBAction)pressStart{
locationManager.delegate = self;
[locationManager startUpdatingLocation];
}
In
- (void)viewDidLoad
{
[super viewDidLoad];
duration.text = #"00:00:00";
speedLabel.text = #"00";
locationManager = [[CLLocationManager alloc]init];
locationManager.distanceFilter = kCLDistanceFilterNone;
locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
}
And this method:
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{
CLLocation *firstLocation = [locations objectAtIndex:0];
location = [locations lastObject];
CLLocationDistance meters = [location distanceFromLocation:firstLocation];
NSLog(#"meters= %f", meters);
And I don't know why the firstLocation is changing. Maybe there is a way to capture firstLocation? This should be the location of the device when the button Start is pressed.
firstLocation in your code is not the first location since location updates started; it is the first location to be returned to you since the previous callback to the locationManager:didUpdateLocations: method (the location services may collect multiple locations before calling back to your delegate method in certain circumstances -- the most recent location is always going to be the last object in the locations array).
If you need to store the first location since location updates started, you should create a property such as
#property (nonatomic, strong) CLLocation *startingLocation;
Then in the locationManager:didUpdateLocations: method, add the code:
if (!self.startingLocation) {
self.startingLocation = [locations objectAtIndex:0];
}
That will store the starting location into the property after the first callback. (You can set the property to nil if you want to reset it.)
Don't forget that the very first location you receive many not be very accurate, as it takes time for location services to get a fix on the device's position if they were not recently enabled.
Hi I am implementing Location services in my app. First I have to know my Coordinates to get the distance between some places that I have in a list and the device. Then if I go into a place I can make a check in, so, I need to get coordinates again, and the problem is here. Second time I try to get coordinates, the method -(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations is not called.. and I can not get new Coordinates.
My manager is located in a NSObject sublcass with this code:
(id)init {
if ( self = [super init] ) {
if ([CLLocationManager locationServicesEnabled])
{
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
[locationManager startUpdatingLocation];
}
}
return self;
}
-(void) checkLongLatitudeAgain {
[locationManager startUpdatingLocation];
}
#pragma mark Delegates de CLLocationManager
//
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{
NSLog(#"LON%f", manager.location.coordinate.longitude);
NSLog(#"LAT:%f", manager.location.coordinate.latitude);
NSTimeInterval howRecentNewLocation = [newLocationeventDate timeIntervalSinceNow];
if (manager.location.horizontalAccuracy <= 100.0 && howRecentNewLocation < -0.0 && howRecentNewLocation > -20.0){
//Usar coordenada
[self.delegate getLocationForCheckIn:manager.location];
[self stopUpdatingLocation:#"Fins"];
}
}
// ---------------------------------------------------------------------------------------------------------------------
-(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error{
//
if ([error code] != kCLErrorLocationUnknown) {
[self stopUpdatingLocation:NSLocalizedString(#"Error", #"Error")];
}
//
}
// ---------------------------------------------------------------------------------------------------------------------
- (void)stopUpdatingLocation:(NSString *)state {
//Detenemos la lectura del GPS
[locationManager stopUpdatingLocation];
locationManager.delegate = nil;
NSLog(#"Stop gps");
//
}
I call the class when the list of places is open, and also when inside a place the user press checkIn button. Both times I do it with this code:
WPLocationManager *location = [[WPLocationManager alloc]init];
[location checkLongLatitudeAgain];
You are creating a new manager every time:
WPLocationManager *location = [[WPLocationManager alloc]init];
[location checkLongLatitudeAgain];
That new manager is not assigned to any delegate.
You need to use the previous manager you have created and assigned to your delegate, something like:
[locationManager checkLongLatitudeAgain];
You can check the documentation at http://developer.apple.com - https://developer.apple.com/library/ios/documentation/userexperience/conceptual/LocationAwarenessPG/CoreLocation/CoreLocation.html
In particular you can check the Starting the Standard Location Service and Starting the Significant-Change Location Service sections. You have to use the startMonitoringSignificantLocationChanges or startUpdatingLocation method of CLLocationManager, cache your location somewhere and update it only when a new location is received, otherwise like it is stated in the documentation: "If a location update has already been delivered, you can also get the most recent location data directly from the CLLocationManager object without waiting for a new event to be delivered".
i dont know why you are initiating your location manager again again, also even if you some how manage to solve current problem but it's not proper way of dealing with location manage based applications.I had been in trouble previously when i was working on location based app. the best approach for location based app is singleton.
apple forum discussion
you can find
this
and this very helpful.
just an advice, :)
Thanks.
In iOS8 for me I had to call [locationManager stopUpdatingLocation]; before calling [locationManager startUpdatingLocation] to start getting updates second time and it works for me.
The following code results in null coordinates. The weird thing is the UIAlert prompting the app to use current location appears briefly before the user can select yes.
My code which i have used :
CLLocationManager *locationManager;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];
locationManager = [[CLLocationManager alloc] init];
locationManager.distanceFilter = kCLDistanceFilterNone;
locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters;
[locationManager startUpdatingLocation];
float latitude = locationManager.location.coordinate.latitude;
float longitude = locationManager.location.coordinate.longitude;
NSLog(#"%.8f",latitude);
NSLog(#"%.8f",longitude);
The NSLog prints 0.0000000 for both coordinates.
Thanks!
The reason you're getting 0 is because the location manager hasn't collected any data at that point (it has started thought)
You need to set your class as the delegate of the location manager (ie supplying a function that is called whenever a new location is retrieved), and also retain your location manager.
// Inside .m file
#interface MyClass () <CLLocationManagerDelegate> // Declare this class to implement protocol CLLocationManagerDelegate
#property (strong, nonatomic) CLLocationManager* locationManager; // Retains it with strong keyword
#end
#implementation MyClass
// Inside some method
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
self.locationManager.distanceFilter = kCLDistanceFilterNone;
[self.locationManager startUpdatingLocation];
// Delegate method
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
CLLocation* loc = [locations lastObject]; // locations is guaranteed to have at least one object
float latitude = loc.coordinate.latitude;
float longitude = loc.coordinate.longitude;
NSLog(#"%.8f",latitude);
NSLog(#"%.8f",longitude);
}