web-dev-qa-db-fra.com

Comment arrêter l'appel de méthodes plusieurs fois de didUpdateLocations () dans ios

C'est mon 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;
 }

Cette méthode consiste à appeler plusieurs fois, ce que je ne veux pas ...

23
user3378632

Ajoutez une restriction ici. Pour la durée entre les emplacements et la précision 

-(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

}
21
nerowolfe

Lors de l'allocation de votre objet LocationManager, vous pouvez définir la propriété distanceFilter de la LocationManager. La propriété de filtre de distance est une valeur CLLocationDistance qui peut être définie pour informer le gestionnaire d'emplacement de la distance parcourue en mètres. Vous pouvez définir le filtre de distance comme suit:

LocationManager *locationManger = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.distanceFilter = 100.0; // Will notify the LocationManager every 100 meters
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
37
Sujith Thankachan

Le moyen le plus simple:

-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations
{
   [manager stopUpdatingLocation];
    manager.delegate = nil;

   //...... do something

}

Le gestionnaire ne peut pas trouver votre méthode didUpdateLocations sans le déléguéreference :-D

Mais n'oubliez pas de le redéfinir avant d'utiliser startUpdatingLocation

20
Raegtime

J'ai une situation similaire. Vous pouvez utiliser 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
    });
}
10

Vous pouvez utiliser une variable statique pour stocker le dernier horodatage d'emplacement, puis le comparer au plus récent, comme ceci:

- (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
}
1
marcelosalloum

pour la contrainte de temps, je n'ai pas compris le code de la réponse acceptée, en affichant une approche différente. comme le souligne Rob "Lorsque vous démarrez les services de localisation pour la première fois, vous pouvez le voir appelé plusieurs fois". le code ci-dessous agit sur le premier emplacement et ignore les emplacements mis à jour pendant les 120 premières secondes. c’est un moyen de répondre à la question initiale "Comment arrêter plusieurs fois l’appel à la méthode didupdateLocations".

dans le fichier .h:

@property(strong,nonatomic) CLLocation* firstLocation;

dans le fichier .m:

// 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
0
tmr

Ecrivez cette méthode lorsque vous souhaitez arrêter de mettre à jour le gestionnaire d'emplacement.

[locationManager stopUpdatingLocation];
0
Charan Giri

Vous pouvez définir un drapeau (Bool). Lorsque vous instanciez votre locationsManager, set flag = true, puis lorsque locationManager: didUpdateLocations, retourne dans un bloc de code .__ que vous ne voulez exécuter qu'une seule fois, définissez flag = false. De cette façon, il ne sera exécuté qu'une seule fois.

 if flag == true {
     flag = false
    ...some code probably network call you only want to run the once 
    }

le gestionnaire d'emplacements sera appelé plusieurs fois, mais le code que vous voulez exécuter une seule fois et je pense que c'est ce que vous essayez d'atteindre.

0
RyanTCB

locationManager.startUpdatingLocation () récupère continuellement l'emplacement et la méthode didUpdateLocations appelle plusieurs fois, Il suffit de définir la valeur de la valeur locationManager.distanceFilter avant d'appeler locationManager.startUpdatingLocation ().

Comme je mets 200 mètres (vous pouvez changer comme votre exigence) fonctionne bien

    locationManager = CLLocationManager()
    locationManager.delegate = self
    locationManager.desiredAccuracy = kCLLocationAccuracyBest
    locationManager.distanceFilter = 200
    locationManager.requestWhenInUseAuthorization()
    locationManager.startUpdatingLocation()
0
Devendra Singh