关于iphone:初始化后,CLLocationManager委托不起作用

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,使用了self = [super init],但仍然没有解决方法:(

GitHub代码
使用locationmanager_init初始化,使用locationmanager_get_heading检索数据


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

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.

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

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

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

与问题无关,但:

您应该最后拨打[super dealloc]而不是先拨打,在这里检查此SO

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

1
2
3
4
5
6
7
8
        ...
        // start the compass
        [locationManager startUpdatingHeading];

        }
    }
    return self;
}


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

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