【问题标题】:Can't allocate CLLocationManager无法分配 CLLocationManager
【发布时间】: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


【解决方案1】:

试试:

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

而不是新的。您确定要将代表分配为自己吗?否则您的班级将不会收听位置更新。

【讨论】:

  • 我 100% 确定。我更改的 only 行是 locationManager = [CLLocationManager new];到 locationManager = [[myAppDelegate appDelegate] locationManager];
  • 更改为 [[CLLocationManager alloc] init] 与 [CLLocationManager new] 的效果相同 - 调用 startUpdatingLocation 时没有任何反应
【解决方案2】:

事实证明,罪魁祸首是一段看似无辜的代码,它在位置管理器启动时就关闭了它。我看到它的唯一原因是因为我将该项目与最近的备份进行了比较,并注意到了差异。由于备份,又解决了一个问题!

【讨论】:

  • 能否请您告诉我关闭位置管理器的原因。我遇到了同样的问题。谢谢。
【解决方案3】:

在定义位置管理器时要小心。 使用 ARC 时,您的位置管理器实例可能会被丢弃。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-06-23
    • 2012-01-20
    • 1970-01-01
    • 1970-01-01
    • 2015-02-20
    • 2016-01-09
    • 1970-01-01
    • 2013-07-03
    相关资源
    最近更新 更多