This my code......
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
location_updated = [locations lastObject];
NSLog(#"updated coordinate are %#",location_updated);
latitude1 = location_updated.coordinate.latitude;
longitude1 = location_updated.coordinate.longitude;
self.lblLat.text = [NSString stringWithFormat:#"%f",latitude1];
self.lblLon.text = [NSString stringWithFormat:#"%f",longitude1];
NSString *str = [NSString stringWithFormat:#"https://maps.googleapis.com/maps/api/geocode/json?latlng=%f,%f&sensor=false",latitude1,longitude1];
url = [NSURL URLWithString:str];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
connection = [NSURLConnection connectionWithRequest:request delegate:self];
if (connection)
{
webData1 = [[NSMutableData alloc]init];
}
GMSMarker *marker = [[GMSMarker alloc] init];
marker.position = CLLocationCoordinate2DMake(latitude1,longitude1);
marker.title = formattedAddress;
marker.icon = [UIImage imageNamed:#"m2.png"];
marker.map = mapView_;
marker.draggable = YES;
}
This method is call multiple times which i don't want.....
While allocating your LocationManager object you can set the distanceFilter property of the LocationManager. Distance filter property is a CLLocationDistance value which can be set to notify the location manager about the distance moved in meters. You can set the distance filter as follows:
LocationManager *locationManger = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.distanceFilter = 100.0; // Will notify the LocationManager every 100 meters
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
The easiest way:
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations
{
[manager stopUpdatingLocation];
manager.delegate = nil;
//...... do something
}
The manager can't find your didUpdateLocations method without the delegate reference :-D
But don't forget to set it again before using startUpdatingLocation
Add some restriction there. For timespan between locations and accuracy
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
CLLocation *newLocation = locations.lastObject;
NSTimeInterval locationAge = -[newLocation.timestamp timeIntervalSinceNow];
if (locationAge > 5.0) return;
if (newLocation.horizontalAccuracy < 0) return;
// Needed to filter cached and too old locations
//NSLog(#"Location updated to = %#", newLocation);
CLLocation *loc1 = [[CLLocation alloc] initWithLatitude:_currentLocation.coordinate.latitude longitude:_currentLocation.coordinate.longitude];
CLLocation *loc2 = [[CLLocation alloc] initWithLatitude:newLocation.coordinate.latitude longitude:newLocation.coordinate.longitude];
double distance = [loc1 distanceFromLocation:loc2];
if(distance > 20)
{
_currentLocation = newLocation;
//significant location update
}
//location updated
}
I have similar situation. You can use dispatch_once:
static dispatch_once_t predicate;
- (void)update
{
if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined &&
[_locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)]) {
[_locationManager requestWhenInUseAuthorization];
}
_locationManager.delegate = self;
_locationManager.distanceFilter = kCLDistanceFilterNone;
_locationManager.desiredAccuracy = kCLLocationAccuracyBest;
predicate = 0;
[_locationManager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
[manager stopUpdatingLocation];
manager = nil;
dispatch_once(&predicate, ^{
//your code here
});
}
locationManager.startUpdatingLocation() fetch location continuously and didUpdateLocations method calls several times,
Just set the value for locationManager.distanceFilter value before calling locationManager.startUpdatingLocation().
As I set 200 meters(you can change as your requirement) working fine
locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.distanceFilter = 200
locationManager.requestWhenInUseAuthorization()
locationManager.startUpdatingLocation()
You can use a static variable to store the latest location timestamp and then compare it to the newest one, like this:
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
[manager stopUpdatingLocation];
static NSDate *previousLocationTimestamp;
CLLocation *location = [locations lastObject];
if (previousLocationTimestamp && [location.timestamp timeIntervalSinceDate:previousLocationTimestamp] < 2.0) {
NSLog(#"didUpdateLocations GIVE UP");
return;
}
previousLocationTimestamp = location.timestamp;
NSLog(#"didUpdateLocations GOOD");
// Do your code here
}
Swift 5 :
If you are looking for a solution in swift.
I tried the accepted answer but it didn't work for me. I tried the below solution by checking the time duration between locations. if it is less than 10 seconds then it will return and the location handler will not update.
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let location = locations.last else {
return
}
let locationAge = -location.timestamp.timeIntervalSinceNow
if locationAge > 10.0 { //10 seconds
return
}
if location.horizontalAccuracy < 0 {
return
}
self.currentLocation = location
print("Location :- \(location.coordinate)")
//location updated
}
Write this method when ever you want to stop updating location manager
[locationManager stopUpdatingLocation];
for the time constraint, i did not understand code from accepted answer, posting a different approach. as Rob points out "When you first start location services, you may see it called multiple times". the code below acts on the first location, and ignores the updated locations for first 120 seconds. it is one way to address orginal question "How to stop multiple times method calling of didUpdateLocations".
in .h file:
#property(strong,nonatomic) CLLocation* firstLocation;
in .m file:
// is this the first location?
CLLocation* newLocation = locations.lastObject;
if (self.firstLocation) {
// app already has a location
NSTimeInterval locationAge = [newLocation.timestamp timeIntervalSinceDate:self.firstLocation.timestamp];
NSLog(#"locationAge: %f",locationAge);
if (locationAge < 120.0) { // 120 is in seconds or milliseconds?
return;
}
} else {
self.firstLocation = newLocation;
}
// do something with location
You could set a flag (Bool). When you instantiate your locationsManager set flag = true then when locationManager:didUpdateLocations returns inside a code block
that you want to run only once set flag = false. This way it will only be run the once.
if flag == true {
flag = false
...some code probably network call you only want to run the once
}
locations manager will be called multiple times but the code you want to execute only once, and I think that is what you are trying to achieve?
you can write :
[manager stopUpdatingLocation];
manager = nil;
in didupdatelocation delegate
A few things worked for me:
setting location manager nil while didUpdateLocations after calling manager.stopUpdatingLocation()
I will suggest setting the location manager to nil is not a good approach.because CLLocationManager sometimes give accurate location in 3-4 times.
What I will suggest change accuracy to kilometers that's worked for me
clLocationManager?.distanceFilter = 1000
clLocationManager?.desiredAccuracy = kCLLocationAccuracyKilometer
Related
How to fetch the location for only one time in ios app.
After getting your location, stop update location manager and also release locationManager because you don't need locationManager anymore.
[self.locationManager stopUpdatingLocation];
self.locationManager.delegate = nil;
self.locationManager = nil;
In ios 9 and above we have a method [locationManagerInstance requestLocation]. But this will take almost ten secs to call back the delegate methods since the location is latest and best.
In another way (for earlier ios9 versions), you could still use the old method [locationManagerInstance startUpdatingLocation] to get the immediate location and also you could validate the timestamp for the best accuracy.
Here is the code that I'm using for getting the location. Create a global reference for locationManager instance.
#interface ViewController ()
{
CLLocationManager *locationManager;
}
Implement these utility methods in your.m file
-(BOOL)canUseLocationManager{
if(([CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorizedWhenInUse) || ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorizedAlways)){
return YES;
}
return NO;
}
-(void) getCurrentLocation {
locationManager.delegate = self;
// ios 9 and above versions only
//[locationManager requestLocation]; // This may take more time when compare to alternate method
// ios 2 and later versions can use this method
[locationManager startUpdatingLocation];
}
-(void) stopGettingCurrentLocation {
[locationManager stopUpdatingLocation];
}
Implement location service delegates
-(void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status{
if([CLLocationManager authorizationStatus] != kCLAuthorizationStatusNotDetermined){
[self doneCheckingAccessStatusForLocation];
}
}
-(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error{
[manager stopUpdatingLocation];
locationManager.delegate = nil;
/* Clean the locationManager instance if you don't need*/
//locationManager = nil;
}
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{
[manager stopUpdatingLocation];
locationManager.delegate = nil;
CLLocation* location = [locations lastObject];
NSDate* eventDate = location.timestamp;
/* Implement your business logics here */
/* Clean the locationManager instance if you don't need*/
//locationManager = nil;
}
Final methods to create the location manager instance and initiate fetching location
-(void)checkForLocationService{
if(!locationManager){
locationManager = [[CLLocationManager alloc] init];
locationManager.distanceFilter = kCLDistanceFilterNone;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
}
locationManager.delegate = self;
if([CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined){
[locationManager requestWhenInUseAuthorization];
}else{
[self doneCheckingAccessStatusForLocation];
}
}
-(void)doneCheckingAccessStatusForLocation{
if([self canUseLocationManager]){
[self getCurrentLocation];
}
}
call the checkForLocationService method and implement your logics on the success and failure delegate methods.
[self checkForLocationService];
UPDATED for iOS9: I am new to iOS, experimenting with CoreLocation to return latitude and longitude values. The following code never executes the log output
-(void)viewWillAppear:(BOOL)animated{
manager = [[CLLocationManager alloc]init];
manager.delegate = self;
manager.desiredAccuracy = kCLLocationAccuracyBest;
[manager startUpdatingLocation];
}
Here is my didUpdateToLocation function with is never reached
- (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray<CLLocation *> *)locations{
NSLog(#"Location: %#", locations);
CLLocation *currentLocation = locations.lastObject;
if (currentLocation != nil) {
float latitude = currentLocation.coordinate.latitude;
float longitude = currentLocation.coordinate.longitude;
NSLog(#"dLongitude : %f", longitude);
NSLog(#"dLatitude : %f", latitude);
}
else{ NSLog(#"ERROR");
}
}
CLLocationManager is asynchronous, You should get the latitude and longitude in the delegate method.
locationManager.delegate = self;
Then implement this delegate method:
- locationManager:didUpdateLocations:
1.first of all, you should use you should use a actual device instead of a simulator
2.implement CLLocationManagerDelegate in the interface,like
#interface XXXXX () <CLLocationManagerDelegate>
3.after
locationManager = [[CLLocationManager alloc] init];
add
locationManager.delegate = self;
4.implement the delegate method
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations
{
for (CLLocation *location in locations) {
//you can get locations here
}
}
I have an iOS app that uses a users current location to show directions/ distance between the users current location and a destination point. I am able to show the destination point on the map, however when I try to get the user's current location using CLlocationManager, it returns coordinates (0,0). Below is my code for retrieving the users location.
Is retrieving current location possible on the Apple Watch?
If so, what am I doing wrong here that the location is returning (0,0)?
CLLocationManager *locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
locationManager.distanceFilter = 5;
CLLocation *location = locationManager.location;
CLLocationCoordinate2D myLoc = CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude);
Also, I have #import < CoreLocation/CoreLocation.h> in my .h file and < CLLocationManagerDelegate>
Try the following code:
#property (nonatomic, strong) CLLocationManager *locationManager;
- (void)willActivate
{
self.locationManager = [[CLLocationManager alloc] init];
[self.locationManager setDelegate:self];
[self.locationManager requestLocation];
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations
{
if ([locations count] == 0) {
// error
return;
}
// success
self.currentLocation = [locations firstObject];
CLLocationCoordinate2D myLoc = CLLocationCoordinate2DMake(
self.currentLocation.coordinate.latitude,
self.currentLocation.coordinate.longitude);
}
- (void)locationManager:(CLLocationManager *)manager
didFailWithError:(nonnull NSError *)error
{
// error
}
If you did not implemented this:
(with attributes inspector or programmatically)
self.mapView.showsUserLocation = YES
Or in addition to tell the mapView that the user's location is depending of LocationManager.location
Is there any way to get the only device gps location using the corelocation in ios.
Currently i am using the following code.
- (id)init{
if (!(self = [super init]))
return nil;
//Setup the manager
manager = [[CLLocationManager alloc] init];
if (!manager) {
return nil;
}
manager.distanceFilter = kCLDistanceFilterNone;
manager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters;
manager.desiredAccuracy = kCLLocationAccuracyBest;
manager.delegate = self;
if ([manager respondsToSelector:#selector(pausesLocationUpdatesAutomatically)]) {
manager.pausesLocationUpdatesAutomatically = NO;
}
if ([manager respondsToSelector:#selector(requestAlwaysAuthorization)])
{
[manager requestAlwaysAuthorization];
}
[manager startUpdatingLocation];
return self;
}
You should add this code to your file. It is executed when a new location is received:
// Delegate method from the CLLocationManagerDelegate protocol.
- (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations {
// If it's a relatively recent event, turn off updates to save power.
CLLocation* location = [locations lastObject];
NSDate* eventDate = location.timestamp;
NSTimeInterval howRecent = [eventDate timeIntervalSinceNow];
if (abs(howRecent) < 15.0) {
// If the event is recent, do something with it.
NSLog(#"latitude %+.6f, longitude %+.6f\n",
location.coordinate.latitude,
location.coordinate.longitude);
}
}
src: Getting the Users Location - Apple
I am a iOS application developer. I am working with Location Manager.
For every 5 seconds I am capturing the latitude and longitude and storing the CLLocation object in array. The lat and long is not completely correct when I am trying to draw those location in Map.
My code is following below:
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{//ios6&+
CLLocation *loc;
NSInteger objCount = [locations count];
if (objCount >= 1) {
loc = [locations objectAtIndex:objCount - 1];
NSArray *Arr_TotalTime = [Str_TotalTime componentsSeparatedByString:#":"];
[ArrayOfLocations addObject:loc];
}
}
Any one can please give me more info to get ACTUAL location (lat, long) from didupdatelocation method.
Any help will be highly appreciated.
Depending on how you set up your location manager, the accuracy will vary.
Try something like this:
Location Manager
_locationManager = [[CLLocationManager alloc] init];
_locationManager.delegate = self;
_locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
_locationManager.activityType = CLActivityTypeAutomotiveNavigation;
_locationManager.distanceFilter = kCLDistanceFilterNone;
Method
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
CLLocation *newLocation = [locations lastObject];
NSDate *eventDate = newLocation.timestamp;
NSTimeInterval howRecent = [eventDate timeIntervalSinceNow];
if ((abs(howRecent) <= 5) && (newLocation.horizontalAccuracy > 0) && (newLocation.verticalAccuracy > 0) && (newLocation.horizontalAccuracy < 100) && (newLocation.verticalAccuracy < 100))
{
[ArrayOfLocations addObject:newLocation];
}
else
{
// received bad signal
}
}
You can use CoreLocation to get the longitude and latitude.
Include framework:
Click your project in navigator.
Click the plus button under "link binary with libraries"
Add Corelocation to your project.
Import the header file:
import
Declare CLLocationManager:
CLLocationManager *locationManager;
initialize locationManager:
- (void)viewDidLoad
{
locationManager = [[CLLocationManager alloc] init];
locationManager.distanceFilter = kCLDistanceFilterNone;
locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters;
[locationManager startUpdatingLocation];
}
Then, use
float latitude = locationManager.location.coordinate.latitude;
float longitude = locationManager.location.coordinate.longitude;