【发布时间】:2011-12-11 05:22:06
【问题描述】:
在我的 UIViewController 的 initWithNibNameOrNil 中,我调用:
locationManager = [CLLocationManager new];
创建对象,然后在viewDidAppear我调用:
[locationManager startUpdatingLocation];
[locationManager startUpdatingHeading];
但我从未收到位置更新;位置管理器从不开始更新位置。但是,如果我将同一行替换为 initWithNibNameOrNil:
locationManager = [[myAppDelegate appDelegate] locationManager];
一切都很好,除了有时会随机崩溃
locationManager.delegate = self;
在位置管理器设置为应用委托中已分配的管理器后的 非常 下一行中设置。这对我来说毫无意义。我不明白为什么一个与另一个不同,更不用说为什么没有一个能始终如一地工作。有人可以请教我吗?
总结:
方法一(不有效):
在 MapView.m 中:
initWithNibNameOrNil:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if(self) {
locationManager = [CLLocationManager new];
locationManager.delegate = self;
locationManager.distanceFilter = kCLHeadingFilterNone;
locationManager.headingFilter = 3;
if(([[UIDevice currentDevice] batteryState] == UIDeviceBatteryStateCharging) || ([[UIDevice currentDevice] batteryState] == UIDeviceBatteryStateFull))
locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
else
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
//more setup irrelevant to the question
}
return self;
}
viewDidAppear:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:YES];
[locationManager startUpdatingLocation];
[locationManager startUpdatingHeading];
}
注意:使用这种创建位置管理器的方法,在 viewDidAppear 中调用 startUpdatingLocation 后,位置服务永远不会启用,因此不会收到位置更新。
方法 2(确实工作,大部分):
在 myAppDelegate.m:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[[UIDevice currentDevice] setBatteryMonitoringEnabled:YES];
self.locationManager = [CLLocationManager new];
self.locationManager.distanceFilter = kCLHeadingFilterNone;
self.locationManager.headingFilter = 3;
if(([[UIDevice currentDevice] batteryState] == UIDeviceBatteryStateCharging) || ([[UIDevice currentDevice] batteryState] == UIDeviceBatteryStateFull))
self.locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
else
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
//more irrelevant setup
}
在 MapView.m 中:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if(self) {
locationManager = [[Trail_TrackerAppDelegate appDelegate] locationManager];
locationManager.delegate = self;
//more irrelevant setup
}
return self;
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:YES];
[locationManager startUpdatingLocation];
[locationManager startUpdatingHeading];
}
注意:这种分配方式有效,除非我推 MapView,然后弹出,再推,再弹出,然后再推,每次在行 initWithNib... 我将委托设置为 self; NSZombieEnabled 说:
-[CLLocationManager setDelegate:]: message sent to deallocated instance 0x9540ad0
有趣...
NSLog(@"%s: %@; %@", PRETTY_FUNCTION, self, locationManager) 说:
-[MapView initWithNibName:bundle:]: <MapView: 0x92ae3e0>; <CLLocationManager: 0x92a3560>
方法3(全能):
在 MapView.m 中:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:YES];
locationManager = [CLLocationManager new];
locationManager.delegate = self;
locationManager.distanceFilter = kCLHeadingFilterNone;
locationManager.headingFilter = 3;
if(([[UIDevice currentDevice] batteryState] == UIDeviceBatteryStateCharging) || ([[UIDevice currentDevice] batteryState] == UIDeviceBatteryStateFull))
locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
else
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];
[locationManager startUpdatingHeading];
}
注意事项:所有的分配和设置都是在viewDidAppear 中完成的,并且在反复推/弹出视图控制器后我没有遇到任何崩溃。这很好,但我不喜欢在viewDidAppear 中分配,因为应用程序滞后了一会儿,因为(我认为)locationManager 的分配阻塞了当时的主线程。我只是真的不明白为什么方法 1 根本不起作用,方法 2 崩溃,而方法 3 起作用。他们不都或多或少做同样的事情吗?
抱歉所有代码,并祝贺所有通过这个迷宫问题的人! :)
【问题讨论】:
-
在调用 [CLLocation new] 之后立即添加此日志语句,并在您要求 startUpdatingLocation:
NSLog("%s: %@; %@", __PRETTY_FUNCTION__, self, locationManager)之前立即添加此日志语句,然后将结果复制/粘贴到您的问题中。 -
看来代码变了?早些时候,您在 init 中执行 [CLLocationManager new]。现在它在 viewDidAppear 中,但您现在似乎没有设置委托。
-
是的,代码改变了。 init 中的 [CLLocationManager new] 无效,但将其放入 viewDidAppear 确实 工作。为了简洁起见,我在剥离方法时不小心省略了设置委托的行。我现在在问题中发布了一个明确的问题。
-
您可以将日志添加到方法 2 中吗?我相信您只将它们添加到方法 3。其中一个日志应该在 init 方法中
-
请将日志添加到方法 2 的 init 和 viewDidAppear 中。这就是我们一直在尝试比较的内容。
标签: iphone ios cllocationmanager