CLLocationManager从不调用委托方法

时间:2011-05-10 21:35:15

标签: iphone objective-c ios ios4 cllocationmanager

嗨,我正在玩iPhone的位置,从一开始就遇到了问题。我已经对我的问题进行了本地化,并确定它是CLLocationManager,这让我烦恼。

所以我开发了非常简单的应用程序。我只有一个带有CLLocationManager的视图控制器。在视图上加载我初始化CLLocationManager并开始更新。我还实现了两种方法didFailWithErrordidUpdateToLocation

我已经阅读了很多问题以及我学到了什么,所以这就是这个。您必须在初始化期间保留CLLocationManager。在卸载CLLocationManagers期间将delegate nil设置为view也是明智的(与传递给CLLocationManager的消息有关,因为框架会保留它并且它永远不会正确释放)

总而言之,我无法找到关于如何做以及如何使其发挥作用的合理解释。

这是我的代码,所以如果有人能搞清楚,我会很感激。 viewControllers头文件

#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>

@interface CoreLocationViewController : UIViewController <CLLocationManagerDelegate>
{
    CLLocationManager *locManager;
}

@property (nonatomic, retain) CLLocationManager *locManager;

@end

viewController .m文件

#import "CoreLocationViewController.h"


@implementation CoreLocationViewController
@synthesize locManager;

- (void)viewDidLoad 
{
    [super viewDidLoad];

    self.locManager = [[CLLocationManager alloc] init];
    locManager.delegate = self;
    [self.locManager startUpdatingLocation];

    self.view.backgroundColor = [UIColor grayColor];
}

#pragma mark -
#pragma mark Location Delegate

- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
        NSLog(@"in fail with error");
}

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
    NSLog(@"in update to location");
}


#pragma mark -
#pragma mark Memory Management

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
}

- (void)viewDidUnload 
{
self.locManager.delegate = nil;
    [super viewDidUnload];
}


- (void)dealloc 
{
    [locManager release];
        [super dealloc];
}


@end

BTW:我使用的是iOS 4.2。我指出这一点是因为我读到Apple已经改变了iOS 4中的位置代表

9 个答案:

答案 0 :(得分:20)

在我的情况下,代理永远不会因为线程问题而被调用

  • 操作LocationManager的线程必须设置NSRunLoop
  • 如果你使用主线程,你已经有了一个runloop,现在你就是这样 需要实例化管理器并在主线程上使用它

Read this to know more about CLLocationManagerDelegate

答案 1 :(得分:8)

此外,在iOS8中,你必须有两件额外的东西:

  • 在Info.plist中添加一个密钥,并请求位置管理员授权启动。

    • NSLocationWhenInUseUsageDescription

    • NSLocationAlwaysUsageDescription

  • 您需要请求相应位置方法的授权。

    • [self.locationManager requestWhenInUseAuthorization]

    • [self.locationManager requestAlwaysAuthorization]

代码示例:

self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
// Check for iOS 8. Without this guard the code will crash with "unknown selector" on iOS 7.
if ([self.locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]) {
    [self.locationManager requestWhenInUseAuthorization];
}
[self.locationManager startUpdatingLocation];

来源:http://nevan.net/2014/09/core-location-manager-changes-in-ios-8/

答案 2 :(得分:4)

其他海报提到检查授权,你一定要加上,但我不认为这是你的问题。如果您未获得授权,则会调用didFailWithError:方法。这导致相信其他事情正在发生。

确保您的位置管理员确实被分配是一个好主意,而在此期间,您可以修复内存泄漏。

试试这个:

CLLocationManager* lm = [[CLLocationManager alloc] init];
NSAssert(lm != nil, @"Failed to allocate CLLocation manage");
self.locManager = lm;
[lm release];
self.locManager.delegate = self;
[self.locManager startUpdatingLocation];
// Let's just print what we got
NSLog(@"CLLocationManager is %@", lm);

如果您执行此操作,您将获得以下结果之一:

1)如果位置管理器返回nil,程序将崩溃到调试器中(因为NSAssert)

2)如果“CLLocationManager is ....”打印并且你仍然没有看到任何更新,那么你手上就会有一个真正的神秘面纱。

3)没有打印。这可能意味着,可能是由于Interface Builder中错误链接的东西,viewDidLoad根本没有被调用。

4)您将获得didFailWithError:电话,因为您未获得授权。这意味着至少一切都按预期工作。

另外,您有内存泄漏,因为您将alloc的结果直接分配给具有retain属性的属性。在分配之后,你的计数在分配后将是+1 + +,所以如果视图被卸载并重新加载,你就会泄漏。

希望其中一些有用。

答案 3 :(得分:3)

这可能是挑剔但在viewDidLoad更改:

locManager.delegate = self;

为:

self.locManager.delegate = self;

我不知道它是否会修复它,但最好保持一致。

答案 4 :(得分:3)

所以我设法找到了一个bug。这是在内存管理。在我的app委托文件中,我初始化了一个CoreLocationViewController并将其作为subview添加到了我的窗口,之后我发布了它,一切都很顺利。但是,释放部分不是一个好方法。在我发布ViewController后,dealloc方法被调用并释放locationManager

因此,正确的做法是不释放持有ViewController的{​​{1}},或者找到另一种处理它的方法。我不太确定为什么这是一个问题,因为我认为在向窗口添加locationManager之后它会被保留,因此它的ViewController也会被保留。如果有人能为我清理它,我将不胜感激。

答案 5 :(得分:2)

你在设备上测试吗?是否启用了位置服务?

if (self.locManager.locationServicesEnabled){
//do domething
}

答案 6 :(得分:0)

Idk如果是一件事,但在我的代码中我也设置了所需的准确度

[locManager setDesiredAccuracy:kCLLocationAccuracyBest];

例如。

答案 7 :(得分:0)

试试这个:

 NSLog(@"location services enabled: %d", [locManager locationServicesEnabled]);

来自文档:

  

用户可以通过在设置&gt;中切换开关,从设置应用程序中完全启用或禁用位置服务。一般&gt;位置服务。

答案 8 :(得分:0)

我遇到了同样的问题,正如paxx所说,这是一个内存管理问题。我的解决方案是手动保留'self'。如下面的代码所示:

- (void) viewDidload 
{
    [super viewDidload];
    if (![CLLocationManager locationServicesEnabled]) {
        NSLog(@"Location Service Disabled!");
    } else {
        [self retain];
        //initialize the cllocationmanager obj.
    }
}


-(void)locationManager:(CLLocationManager *)manager 
    didUpdateLocations:(NSArray *)locations
{
    //do your surf
    [self release];
}


-(void)locationManager:(CLLocationManager *)manager 
   didUpdateToLocation:(CLLocation *)newLocation 
          fromLocation:(CLLocation *)oldLocation
{
    //do your stuff
    [self release];
}

-(void)locationManager:(CLLocationManager *)manager 
      didFailWithError:(NSError *)error
{
    //do your stuff
    [self release];
}

不漂亮,但对我来说很好。