【问题标题】:CLLocationManager delegates not working after initializationCLLocationManager 委托在初始化后不工作
【发布时间】:2012-08-26 10:26:50
【问题描述】:

我正在尝试让 iphone 的指南针使用 rhomobile 框架工作。 我已经完成了 rhomobile 部分,创建了一个在 iphone 上调用本机方法的工作包装器,但我无法让事件正常工作。

Locationmanager.h

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

@interface locationController : NSObject <CLLocationManagerDelegate> 
{
    CLLocationManager *locationManager;
}
@property (strong, nonatomic) CLLocationManager *locationManager;

- (id)init;
- (void)dealloc;

@end

Locationmanager.m

#import "Locationmanager.h"

#include "ruby/ext/rho/rhoruby.h"

//store the values
double gx, gy, gz, gth;

//init location
locationController *lc;
@implementation locationController

@synthesize locationManager;

- (id)init {
if (self = [super init]) {
    self.locationManager = [[CLLocationManager alloc] init];

    NSLog(@"%@", [CLLocationManager headingAvailable]? @"\n\nHeading available!\n" : @"\n\nNo heading..\n");
    NSLog(@"%@", [CLLocationManager locationServicesEnabled]? @"\n\nLocation available!\n" : @"\n\nNo location..\n");

    // check if the hardware has a compass
    if ([CLLocationManager headingAvailable] == NO) {
        // No compass is available. This application cannot function without a compass, 
        // so a dialog will be displayed and no magnetic data will be measured.
        locationManager = nil;
        UIAlertView *noCompassAlert = [[UIAlertView alloc] initWithTitle:@"No Compass!" message:@"This device does not have the ability to measure magnetic fields." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
        [noCompassAlert show];
        [noCompassAlert release];
        NSLog(@"\n***** ERROR *****\n No compass found !!!");
    } else {
        // setup delegate callbacks
        locationManager.delegate = self;

        // heading service configuration
        locationManager.headingFilter = kCLHeadingFilterNone;

        // location service configuration
        locationManager.distanceFilter = kCLDistanceFilterNone;
        locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters;

        //start location services
        [locationManager startUpdatingLocation];

        // start the compass
        [locationManager startUpdatingHeading];

    }
return self;
}
}
- (void)dealloc {    
    [super dealloc];
    // Stop the compass
    [locationManager stopUpdatingHeading];
    [locationManager release];
}

// This delegate method is invoked when the location manager has heading data.
- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)heading {
    NSLog(@"\n\n***** New magnetic heading *****\n %f\n", heading.magneticHeading);
    NSLog(@"\n\n***** New true heading *****\n %f\n", heading.trueHeading);
    gx = heading.x;
    gy = heading.y;
    gz = heading.z;
    gth = heading.trueHeading;
}

// This delegate method is invoked when the location managed encounters an error condition.
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
    if ([error code] == kCLErrorDenied) {
        // This error indicates that the user has denied the application's request to use location services.
        NSLog(@"\n ***** ERROR *****\n Location not allowed!");
        [locationManager stopUpdatingHeading];
    } else if ([error code] == kCLErrorHeadingFailure) {
        NSLog(@"\n ***** ERROR *****\n Magnetic interference or something!");
    }
}

@end

//ruby wrappers
void locationmanager_init(void) {
   // make sure we can only start this method once
   static bool started = false;
   if(!started) {
       // Initialize the Objective C accelerometer class.
       lc = [[locationController alloc] init];
       started = true;
   }

}

void locationmanager_get_heading(double *x, double *y, double *z, double *th) {
    NSLog(@"\n ***** DEBUGGER *****\n Getting heading  x: %f, y: %f, z: %f, heading: %f", gx, gy, gz, gth);
    *x = gx;
    *y = gy;
    *z = gz;
    *th = gth;
}

我在带有 iOS 5.1 的 iphone 4 上运行代码,在控制台中我可以看到 init 的调试消息,但我从未看到 didUpdateHeading 委托的调试消息。有人知道我在这里错过了什么吗?

更新

我认为我需要在后台线程中运行我的代码才能使其正常工作。当前 locationmanager_init 初始化 + 离开代码,因此它不活动并且不会触发事件。 任何人有一个简单的解决方案在后台初始化它以保持它的活跃?

更新 2

返回 id,使用 self = [super init] 仍然没有修复:(

GitHub code 用 locationmanager_init 初始化,用 locationmanager_get_heading 检索数据

【问题讨论】:

  • 我在 .h 文件中定义和不定义委托都试过了。还使用了 UIViewController 而不是 NSObject,就像在 Apple 的 Teslameter 示例中所做的那样,仍然没有进展:(
  • 我把扩展码放在Github
  • 在 Locationmanager.m 文件中,您可以看到当我进入视图时调用的 locationmanager_init 方法,以及如果有人想要检索标题时调用的 locationmanager_getheading。
  • 您确定您的代表没有提前到达dealloc

标签: iphone ios delegates cllocationmanager rhomobile


【解决方案1】:

您必须在主线程上初始化CLLocationManager,检查此 SO here,或从具有活动运行循环的线程运行它,检查此 SO here,来自 Apple 文档:

Configuration of your location manager object must always occur on a thread with 
an active run loop, such as your application’s main thread.

确保您的locationController 和其中的CCLocationManager 在初始化之后仍然存在,检查here。我在这里可能错了,但是从您的 Github 代码来看,*lc 变量似乎正在自动释放池中释放。尝试给它一个额外的保留。

lc = [[[locationController alloc] init] retain];

我想这是你的问题的原因。如果对象被释放,您将不会得到任何更新。

与问题无关,但:

你应该最后而不是第一个打电话给[super dealloc],检查这个SO here

将 return 语句放在 init 方法中最后一个括号之前,而不是在倒数第二个之前。

        ...
        // start the compass
        [locationManager startUpdatingHeading];

        }
    }
    return self;
}

【讨论】:

  • 我试过了,更新了github上的代码。在 xcode 的控制台中,我没有看到任何标题出现,但是我遇到了一些我以前从未见过的错误:Sep 13 13:00:44 unknown CommCenter[56] &lt;Error&gt;: kDataAttachStatusNotification sent, wasAttached: 1 isAttached: 1
  • 在将您的答案与performSelectorOnMainThread 结合后,它起作用了!!感谢您的帮助,我已经坚持了大约 7 周了 :) 您可以想象我现在可以继续我的发展有多高兴。工作代码更新@github
  • 我也遇到了它在另一个线程上的问题。我不敢想如果没有你的回答,我要花多长时间才能弄清楚,所以非常感谢!
【解决方案2】:
- (void)locationManager:(CLLocationManager *)manager 
didUpdateHeading:(CLHeading *)heading;
- (void)locationManager:(CLLocationManager *)manager 
didFailWithError:(NSError *)error;

这些是您的实例方法,而不是委托方法。

检查 https://developer.apple.com/library/mac/#documentation/CoreLocation/Reference/CLLocationManagerDelegate_Protocol/CLLocationManagerDelegate/CLLocationManagerDelegate.html

【讨论】:

  • 问题是针对 iOS 的(它有一个 didUpdateHeading 委托方法)。您的链接指向 OS X 文档。
【解决方案3】:

这可能不是整体问题的解决方案,但您的 init 方法缺少返回语句:

- (id)init {
  if (self = [super init]) {
    // do your setup here
  }

  return self;
}

【讨论】:

  • 我一直在玩各种形式的初始化,但我忘了把它放回去:P 虽然它没有解决任何问题,但它应该在那里,谢谢你的报告!
  • 我也认为问题出在您的 [init] 上。从您的代码片段中,您需要显式设置 self = [super init],因为 self 尚未准备好,除非您按照 tilo 的建议进行操作,if( self= [超级初始化]) {...}。祝你好运!
  • 试过了,没有解决,太糟糕了:(
猜你喜欢
  • 2011-11-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-03
  • 2017-05-16
相关资源
最近更新 更多