【问题标题】:How to stop multiple times method calling of didUpdateLocations() in ios如何在 ios 中停止多次调用 didUpdateLocations() 方法
【发布时间】:2014-04-13 02:57:46
【问题描述】:

这是我的代码......

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

这个方法被多次调用,我不想要.....

【问题讨论】:

  • 那为什么要调用这个方法呢?
  • 每五分钟更新一次位置。
  • 当您第一次启动定位服务时,您可能会看到它被多次调用,并且位置越来越准确(例如,减少 horizontalAccuracy)。还要设置CLLocationManager 属性distanceFilterdesiredAccuracy 来控制调用频率。
  • Swift 3 版本接受的答案stackoverflow.com/a/43066729/7250862

标签: ios iphone cllocationmanager cllocation


【解决方案1】:

在分配LocationManager 对象时,您可以设置LocationManagerdistanceFilter 属性。距离过滤器属性是一个CLLocationDistance 值,可以设置它以通知位置管理器移动的距离(以米为单位)。您可以按如下方式设置距离过滤器:

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

【讨论】:

  • 首先停止更新位置,因为所选答案只会停止进一步处理,所以我认为这应该是更好的选择
  • 优秀的答案。我从来不明白人们如何认为在函数开头设置 return sttmnt 解决了一些问题....
  • 不适合我,总是在开始时获得 3 个更新
【解决方案2】:

在那里添加一些限制。对于位置和准确性之间的时间跨度

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

}

【讨论】:

  • 最好移一行:if(distance &gt; 20) { _currentLocation = newLocation; //significant location update }
  • @nerowolfe,谢谢,但我对代码有疑问: if (newLocation.horizo​​ntalAccuracy
  • 试图过滤不正确的位置(在这种情况下,它们的准确性是错误的)
  • 没有更新的位置,didFailWithError 怎么样?
【解决方案3】:

最简单的方法:

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

   //...... do something

}

没有 delegate 参考,经理找不到您的 didUpdateLocations 方法:-D

但不要忘记在使用 startUpdatingLocation

之前再次设置它

【讨论】:

  • 这非常有效,因为它只在管理器的特定实例上更新一次位置。谢谢!
  • 为什么不简单地使用 locationManager.requestLocation() 来获取一次位置? didUpdateLocations 中的 stopUpdatingLocation 没有多大意义,可能只是作为 iOS8 上的一种解决方法(其中 .requestLocation() 不可用)
【解决方案4】:

我也有类似的情况。您可以使用 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
    });
}

【讨论】:

    【解决方案5】:

    locationManager.startUpdatingLocation() 连续获取位置,didUpdateLocations 方法调用多次, 只需在调用 locationManager.startUpdatingLocation() 之前设置 locationManager.distanceFilter 的值即可。

    因为我设置了 200 米(您可以根据需要更改)工作正常

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

    【讨论】:

    • 我应用了这个,但它在开始位置更新时调用了 3 次
    【解决方案6】:

    您可以使用静态变量来存储最新的位置时间戳,然后将其与最新的进行比较,如下所示:

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

    【讨论】:

    • 暂停模式?你到底想做什么?如果您想确保它可以在后台运行,您应该启动UIBackgroundTask。如果你想监控位置更新,你应该使用startMonitoringSignificantLocationChanges
    • 同样的事情我做了 UIBackgroundTask 感谢重播。 :)
    【解决方案7】:

    当您想停止更新位置管理器时编写此方法

    [locationManager stopUpdatingLocation];
    

    【讨论】:

    【解决方案8】:

    由于时间限制,我不理解已接受答案中的代码,因此发布了不同的方法。正如 Rob 指出的那样“当您第一次启动定位服务时,您可能会看到它被多次调用”。下面的代码作用于第一个位置,并在前 120 秒内忽略更新的位置。这是解决原始问题“如何停止对 didUpdateLocations 的多次方法调用”的一种方法。

    在 .h 文件中:

    @property(strong,nonatomic) CLLocation* firstLocation;
    

    在 .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
    

    【讨论】:

    • @kalpesh,我不知道你的问题的答案,我搬到了另一个项目。
    【解决方案9】:

    您可以设置一个标志 (Bool)。当您实例化您的位置管理器设置标志 = true 时,位置管理器:didUpdateLocations 在代码块内返回 您只想运行一次设置标志 = false。这样它只会运行一次。

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

    locations manager 将被多次调用,但您只想执行一次代码,我认为这就是您想要实现的目标?

    【讨论】:

      【解决方案10】:

      你可以写: [经理停止更新位置]; 经理=无; 在 didupdatelocation 委托中

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-10-20
        • 1970-01-01
        • 1970-01-01
        • 2016-10-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-07-22
        相关资源
        最近更新 更多