CLLocationManager 从不调用委托方法[重复]

Posted

技术标签:

【中文标题】CLLocationManager 从不调用委托方法[重复]【英文标题】:CLLocationManager never calls delegate methods [duplicate] 【发布时间】:2011-05-10 21:35:15 【问题描述】:

您好,我在 iPhone 上玩弄地点,从一开始我就遇到了问题。我已经定位了我的问题并确定是 CLLocationManager 困扰着我。

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

我已经阅读了很多问题,我学到的就是这个。您必须在初始化期间保留CLLocationManager。在卸载view 期间将CLLocationManagers delegate 设置为nil 也是明智之举(这与传递给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

顺便说一句:我使用的是 ios 4.2。我指出这一点是因为我读到 Apple 在 iOS 4 中更改了位置代表

【问题讨论】:

你在这里泄漏,因为 self.locManager = [[CLLocationManager alloc] init];将对象保留在使用 alloc init 获得的引用计数之上。 【参考方案1】:

在我的例子中,由于线程问题,委托永远不会被调用

操作LocationManager的线程必须有一个NSRunLoop集 向上 如果你使用主线程,你已经有一个运行循环,现在你只需 需要实例化管理器并在主线程上使用它

Read this to know more about CLLocationManagerDelegate

【讨论】:

完美。为我修好了。我之前已经尝试过了,但只确保了 startUpdatingLocation 方法。实际上,alloc/init 等也必须在主线程上! 答案!在与主线程不同的队列上实例化 CLLocationManager 是我的问题。将调用调度到主线程修复它。 @TimBodeit 这当然为我解决了这个问题。但我不明白的是以前我是从viewDidLoad 调用它的。 viewDidLoad 不是从主线程运行的吗?【参考方案2】:

此外,在 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/

【讨论】:

【参考方案3】:

其他发帖人提到了检查授权,你绝对应该补充一下,但我认为这不是你的问题。如果您未获得授权,您的 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: 电话,因为你没有被授权。这意味着至少一切都按预期工作。

顺便说一句,您有内存泄漏,因为您将分配的结果直接分配给具有retain 属性的属性。在分配之后,您的计数将在分配后为 +1,它将为 +2,因此如果视图被卸载并重新加载,您将泄漏。

希望这能有所帮助。

【讨论】:

试过了.. 我得到了一个可疑的 CLLocationManager 是 .. 我认为还有更多的东西.. 可能我电脑上的 locationFramework 没有正确安装.. 你知道吗任何项目,或者你有和项目使用 locationManager 并且工作 100%.. 我想测试它是我的代码还是其他东西.. 顺便说一句:tnx for alloc 的东西.. 不知道.. 曾经是一个.NET 编码器,所以我仍在尝试适应没有垃圾收集器的环境 我正在使用模拟器,因为我没有自己的开发者账户。但我今天要在朋友账户上尝试一下,看看设备上会发生什么。但我很困惑一方面..它至少不应该在模拟器上调用错误委托吗?还是在模拟器上什么都没有发生是正常的??? @paki 在我的模拟器版本 4.2 中,它确实可以正确调用(尽管您只获得了一些更新)。我不记得在早期版本中发生了什么。【参考方案4】:

这可能有点挑剔,但在 viewDidLoad 中发生了变化:

locManager.delegate = self;

到:

self.locManager.delegate = self;

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

【讨论】:

这个修复对我有用。【参考方案5】:

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

所以正确的做法是不要释放包含locationManagerViewController,或者寻找其他处理方式。我不太清楚为什么这是一个问题,因为我认为在将ViewController 添加到窗口后它会被保留,因此它的localtionManager 也会被保留。如果有人可以为我清理它,将不胜感激。

【讨论】:

没有。将视图控制器的视图添加到窗口后,它的 VIEW 被保留,但视图本身不被保留。这是一个旧帖子,但仍然值得评论。当发生的任何事情(例如点击按钮)试图调用视图控制器的方法之一时,释放屏幕上的视图控制器可能会导致崩溃。【参考方案6】:

您在设备上进行测试吗?是否启用了定位服务?

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

【讨论】:

试过了。我用了if ([CLLocationManager locationServicesEnabled]) [self.locManager startUpdatingLocation]; ,但没有用。我认为还有更多内容 核心定位框架肯定已添加到您的构建中? 是的..没有它就无法运行【参考方案7】:

Idk 如果这是一个问题,但在我的代码中我还设置了所需的准确性

[locManager setDesiredAccuracy:kCLLocationAccuracyBest];

例如。

【讨论】:

【参考方案8】:

试试这个:

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

来自文档:

用户可以通过在“设置”>“常规”>“定位服务”中切换开关,从“设置”应用程序中完全启用或禁用定位服务。

【讨论】:

试过了。我用了if ([CLLocationManager locationServicesEnabled]) [self.locManager startUpdatingLocation]; ,但没有用。我认为还有更多内容 NSLog 声明说了什么?您的 loc 服务是否启用?如果它们被禁用,if 语句将不会启用它们 - 您必须在“设置”应用中执行此操作。 服务已启用.. 但我在模拟器上运行,我不确定在模拟器上运行是否会调用任何委托.. 我想它至少应该调用错误委托 是的,模拟器对代理进行 GPS 回调。在这一点上,我会进行清理和重建,并确保您执行 IOS 模拟器/重置内容和设置...以确保不缓存一些时髦的东西。【参考方案9】:

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

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

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

【讨论】:

以上是关于CLLocationManager 从不调用委托方法[重复]的主要内容,如果未能解决你的问题,请参考以下文章

CLLocationManager 委托方法 didUpdateToLocation 没有被调用

CLLocationManager 如何根据 iOS 版本调用正确的委托方法

XCTest CLLocationManager 的委托方法不会被调用

CLLocationManager委托方法未被调用

在 iOS 11 和 Xcode 9.1 中未调用 CLLocationManager 的 didUpdateLocations 委托 [重复]

UIPickerView 委托在以编程方式创建时从不调用