CLLocationManager delegates not working after initialization
我正在尝试使iPhone的指南针能够使用Rhomobile框架工作。
我已经做过rhomobile的一部分,创建了一个工作包装器,该包装器在iPhone上调用了本机方法,但是我无法设法使事件起作用。
Locationmanager.h
1 2 3 4 5 6 7 8 9 10 11 12 13 | #import <UIKit/UIKit.h> #import <CoreLocation/CoreLocation.h> @interface locationController : NSObject <CLLocationManagerDelegate> { CLLocationManager *locationManager; } @property (strong, nonatomic) CLLocationManager *locationManager; - (id)init; - (void)dealloc; @end |
位置管理器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | #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]? @"\ \ Heading available!\ " : @"\ \ No heading..\ "); NSLog(@"%@", [CLLocationManager locationServicesEnabled]? @"\ \ Location available!\ " : @"\ \ No location..\ "); // 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(@"\ ***** ERROR *****\ 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(@"\ \ ***** New magnetic heading *****\ %f\ ", heading.magneticHeading); NSLog(@"\ \ ***** New true heading *****\ %f\ ", 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(@"\ ***** ERROR *****\ Location not allowed!"); [locationManager stopUpdatingHeading]; } else if ([error code] == kCLErrorHeadingFailure) { NSLog(@"\ ***** ERROR *****\ 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(@"\ ***** DEBUGGER *****\ 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,使用了
GitHub代码
使用locationmanager_init初始化,使用locationmanager_get_heading检索数据
您必须在主线程上初始化
1 2 | Configuration of your location manager object must always occur on a thread with an active run loop, such as your application’s main thread. |
确保您的
1 | lc = [[[locationController alloc] init] retain]; |
我想这是造成您问题的原因。如果对象被释放,您将不会获得任何更新。
与问题无关,但:
您应该最后拨打
将return语句放在init方法的最后一个括号之前,而不是倒数第二个括号之前。
1 2 3 4 5 6 7 8 | ... // start the compass [locationManager startUpdatingHeading]; } } return self; } |
可能这不是整体问题的解决方案,但是您的
1 2 3 4 5 6 7 | - (id)init { if (self = [super init]) { // do your setup here } return self; } |
1 2 3 4 | - (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