Objective C,iOS 7 - CLLocationManager:didUpdateLocations 只被调用一次

Posted

技术标签:

【中文标题】Objective C,iOS 7 - CLLocationManager:didUpdateLocations 只被调用一次【英文标题】:Objective C, iOS 7 - CLLocationManager: didUpdateLocations is being called only once 【发布时间】:2014-02-14 00:16:26 【问题描述】:

编辑:好的,我刚刚注意到这个问题是 ios 7 独有的。但是我仍然无法解决它,所以我想我会尝试下面的建议。谢谢大家!

¡嗨!我正在编写一个导航器应用程序,我需要尽可能更新用户位置。我有两个使用 CLLocation 管理器的视图控制器。在他们两个中,我都添加了这一行:

#import <CoreLocation/CoreLocation.h>

然后添加到接口声明中,我将其设置为.h文件中的属性,然后合成:

@property (strong, nonatomic) CLLocationManager *locationManager;

之后,我在 viewDidLoad 中启动 de locationManager,这样:

if(self)
    locationManager = [[CLLocationManager alloc] init];
    //locationManager.delegate = self;
    [locationManager setDelegate:self];
    [locationManager setDistanceFilter:kCLHeadingFilterNone];
    [locationManager setDesiredAccuracy:kCLLocationAccuracyBestForNavigation];
    [locationManager startUpdatingLocation];

这是我的委托方法。

对于第一个视图:

#pragma mark - CLLocationManagerDelegate

- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error

    NSLog(@"didFailWithError: %@", error);
    UIAlertView *errorAlert = [[UIAlertView alloc]
                           initWithTitle:@"Error" message:@"Failed to Get Your Location" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
    [errorAlert show];


- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation

    NSLog(@"didUpdateToLocation: %@", newLocation);
    CLLocation *currentLocation = newLocation;

    if (currentLocation != nil) 
        homeLatitude = [[NSString stringWithFormat:@"%.8f",  currentLocation.coordinate.latitude] doubleValue];
        homeLongitude = [[NSString stringWithFormat:@"%.8f", currentLocation.coordinate.longitude] doubleValue];
        NSLog(@"Updated! -> hl = %f, hlg = %f", homeLatitude, homeLongitude);
    

对于第二个视图。如您所见,我用 didUpdateLocations 替换了旧的 didUpdateToLocation,这是一次绝望的尝试。

#pragma mark - CLLocationManagerDelegate

- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error

    NSLog(@"didFailWithError: %@", error);
    UIAlertView *errorAlert = [[UIAlertView alloc]
                           initWithTitle:@"Error" message:@"Failed to Get Your Location"       delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
    [errorAlert show];


/*- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation   *)newLocation fromLocation:(CLLocation *)oldLocation

    NSLog(@"didUpdateToLocation: %@", newLocation);
    CLLocation *currentLocation = newLocation;

    if (currentLocation != nil) 
        NSLog(@"Tarzan boy");
        _testLabel.text = [NSString stringWithFormat:@"Oh DAMN!!!!"];
    
*/

-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations 
    NSLog(@"didUpdateToLocation: %@", [locations lastObject]);
    CLLocation *currentLocation = [locations lastObject];
    if (currentLocation != nil) 
        currentLatitude = [[NSString stringWithFormat:@"%.8f", currentLocation.coordinate.latitude] doubleValue];
        currentLongitude = [[NSString stringWithFormat:@"%.8f", currentLocation.coordinate.longitude] doubleValue];
        NSLog(@"Updated! (MapWithRoutesViewController) -> hl = %f, hlg = %f", currentLatitude, currentLongitude);
        _testLabel.text = [NSString stringWithFormat:@"Update! -> hl = %f, hlg = %f", currentLatitude, currentLongitude];

        //Aquí es donde borramos el lugar al que llegaron.
        if(mapView)
            if(followMe)
                CLLocationCoordinate2D *c = &((CLLocationCoordinate2D).latitude = currentLatitude, .longitude = currentLongitude);
                [mapView.mapView as_setCenterCoordinate:*c zoomLevel:32 animated:NO];
                _ourStepper.value = [mapView.mapView as_zoomLevel];
            

        if([mapView getNearestDestinyDistance:currentLocation] < 150.0)
            NSLog(@"Hay que eliminar el primer destino del MapView");
            mapView.destinoActual++;
        

        if([mapView getNearestPointDistance:currentLocation] > 200.0)
            NSLog(@"Hay que recalcular la ruta al destinoActual");
            SpinnerView *spinner = [SpinnerView loadSpinnerIntoView:self.view];
            spinner.tag = 98;
            while (![mapView recalculateRoutesTo:currentLocation]) 
                //do nothin...
            
            [spinner removeSpinner];

        
    

//[locationManager stopUpdatingLocation];

如你所见,这条线

//[locationManager stopUpdatingLocation];

被评论。好吧,让我发疯的问题是,上面的代码在第一个视图控制器中起到了魅力,并按照我的预期定期更新。但是在第二种视图中,它只在第一次工作,并且永远不会再次更新。我在不同的时间编写了这些方法,所以我不记得我是否对第一个视图做了一些我没有对第二个视图做的事情。但它们在同一个应用程序中,所以我认为库或权限没有问题。欢迎任何帮助或提示,谢谢!

【问题讨论】:

【参考方案1】:

首先,如果您在进行导航,您应该注册重大更改通知。去阅读那个here 的文档。它效率更高。当您不使用它时,您必须将其关闭,但它会好得多。对它的支持可以追溯到 iOS 4。这肯定是 99% 的用户群体。

【讨论】:

好的,我会检查你建议的文档,看起来不错。谢谢!【参考方案2】:

我在我的应用程序中遇到了类似的情况,并实现了一个单例来处理所有位置更新,然后将 NSNotificaitons 触发到前台线程。

创建一个单例类来处理 View 的位置更新 注册以收听 LOCATION_CHANGE 更新可能是后台 单例对象注册为位置管理器的委托

这可能不是您正在寻找的答案,但我知道它在我的情况下有效。

【讨论】:

感谢您的回答!听起来很合理,但我对单身人士不太熟悉。我将从文档开始,但如果你有一些代码要分享,那就太棒了!谢谢!【参考方案3】:

找到解决方案here。当我以这种方式启动 locationManager 时,它可以工作:

if(self)
     locationManager = [[CLLocationManager alloc] init];
     [locationManager setDelegate:self];
     [locationManager setDistanceFilter:kCLHeadingFilterNone];
     //change the desired accuracy to kCLLocationAccuracyBest
     [locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
     //SOLUTION: set setPausesLocationUpdatesAutomatically to NO
     [locationManager setPausesLocationUpdatesAutomatically:NO];
     [locationManager startUpdatingLocation];

无论如何,我都会像 Rob 建议的那样工作。感谢大家的帮助!

【讨论】:

以上是关于Objective C,iOS 7 - CLLocationManager:didUpdateLocations 只被调用一次的主要内容,如果未能解决你的问题,请参考以下文章

《iOS开发全然上手——使用iOS 7和Xcode 5开发移动与平板应用》之Objective-C新手训练营

如何在 iOS 7 的 UIWebView 中从 JavaScript 调用 Objective-C?

IOS 7锁定屏幕Objective-C的警报本地通知

Objective C iOS简单图像旋转类

Effective Objective -C 第一章 熟悉iOS

Objective-C iOS应用程序中的C风格函数[关闭]