简体   繁体   English

如何在ios中多次停止调用didUpdateLocations()的方法

[英]How to stop multiple times method calling of didUpdateLocations() in ios

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 . 虽然分配好自己的LocationManager对象,你可以设置distanceFilter的财产LocationManager Distance filter property is a CLLocationDistance value which can be set to notify the location manager about the distance moved in meters. 距离过滤器属性是CLLocationDistance值,可以将其设置为通知位置管理器有关以米为单位移动的距离。 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;

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

}

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 如果没有委托引用,管理器找不到您的didUpdateLocations方法:-D

But don't forget to set it again before using startUpdatingLocation 但是在使用startUpdatingLocation之前不要忘记再次设置它

I have similar situation. 我有类似的情况。 You can use dispatch_once: 你可以使用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
    });
}

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
}

如果要停止更新位置管理器,请编写此方法

[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". 正如Rob指出的那样“当你第一次启动位置服务时,你可能会多次看到它被调用”。 the code below acts on the first location, and ignores the updated locations for first 120 seconds. 下面的代码作用于第一个位置,并在前120秒忽略更新的位置。 it is one way to address orginal question "How to stop multiple times method calling of didUpdateLocations". 它是解决原始问题“如何停止多次调用didUpdateLocations的方法”的一种方法。

in .h file: 在.h文件中:

@property(strong,nonatomic) CLLocation* firstLocation;

in .m file: 在.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

You could set a flag (Bool). 你可以设置一个标志(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. 当您实例化您的locationsManager set flag = true时,当locationManager:didUpdateLocations在您想要仅运行一次的代码块内返回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? 位置管理器将被多次调用,但是您只想执行一次代码,我认为这是您要实现的目标?

locationManager.startUpdatingLocation() fetch location continuously and didUpdateLocations method calls several times, Just set the value for locationManager.distanceFilter value before calling locationManager.startUpdatingLocation(). locationManager.startUpdatingLocation()连续获取位置并且didUpdateLocations方法调用多次,只需在调用locationManager.startUpdatingLocation()之前设置locationManager.distanceFilter值的值。

As I set 200 meters(you can change as your requirement) working fine 因为我设置200米(你可以根据你的要求改变)工作正常

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

you can write : [manager stopUpdatingLocation]; 你可以写:[经理stopUpdatingLocation]; manager = nil; 经理=零; in didupdatelocation delegate 在didupdatelocation委托中

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM