CLLocationManager 从不调用委托方法[重复]
Posted
技术标签:
【中文标题】CLLocationManager 从不调用委托方法[重复]【英文标题】:CLLocationManager never calls delegate methods [duplicate] 【发布时间】:2011-05-10 21:35:15 【问题描述】:您好,我在 iPhone 上玩弄地点,从一开始我就遇到了问题。我已经定位了我的问题并确定是 CLLocationManager
困扰着我。
所以我开发了非常简单的应用程序。我只有一个带有CLLocationManager
的视图控制器。在视图确实加载我初始化CLLocationManager
并开始更新。我还实现了两种方法didFailWithError
和didUpdateToLocation
。
我已经阅读了很多问题,我学到的就是这个。您必须在初始化期间保留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 是这可能有点挑剔,但在 viewDidLoad 中发生了变化:
locManager.delegate = self;
到:
self.locManager.delegate = self;
我不知道它是否会解决它,但最好保持一致。
【讨论】:
这个修复对我有用。【参考方案5】:所以我设法找到了一个错误。它在内存管理中。在我的应用程序委托文件中,我初始化了一个CoreLocationViewController
并将其作为subview
添加到我的窗口中,之后我发布了它,一切都很好。但是,发布部分并不是一个好方法。在我发布了我的ViewController
之后,dealloc
方法被调用并发布了locationManager
。
所以正确的做法是不要释放包含locationManager
的ViewController
,或者寻找其他处理方式。我不太清楚为什么这是一个问题,因为我认为在将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 的委托方法不会被调用
在 iOS 11 和 Xcode 9.1 中未调用 CLLocationManager 的 didUpdateLocations 委托 [重复]