2012-08-31 23 views
5

Estoy tratando de hacer funcionar la brújula del iphone utilizando el marco rhomobile. Ya hice la parte de rhomobile, creé un contenedor de trabajo que llama a métodos nativos en el iphone, pero no puedo lograr que los eventos funcionen.Los delegados de CLLocationManager no funcionan después de la inicialización

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; 
} 

estoy ejecutando el código en un iPhone 4 con iOS 5.1, en la consola puedo ver los mensajes de depuración de init, pero nunca veo un mensaje de depuración del delegado didUpdateHeading. ¿Alguien tiene una pista de lo que extrañé aquí?

ACTUALIZACIÓN

Creo que necesito para ejecutar el código en un subproceso de fondo para conseguir que funcione. Actualmente el locationmanager_init inicializa + deja el código, por lo tanto no está activo y los eventos no se disparan. ¿Alguien tiene una solución simple inicializando esto en el fondo para mantenerlo activo?

ACTUALIZACIÓN 2

devolvió el ID, utiliza self = [super init] y todavía hay una solución :(

GitHub code Inicializa con locationmanager_init, recupera los datos con locationmanager_get_heading

+0

Tenga una mirada en https://developer.apple.com/library/mac/#documentation/CoreLocation/Reference/CLLocationManagerDelegate_Protocol/CLLocationManagerDelegate/CLLocationManagerDelegate.html – fibnochi

+0

he probado con y sin definir los delegados en el .h archivo. También usé UIViewController en lugar de NSObject, como se hizo en el ejemplo del Teslameter de Apple, todavía no hay progreso :( – Vikko

+0

envíeme su código por correo electrónico. – fibnochi

Respuesta

13

Usted tiene que inicializar el CLLocationManager en el hilo principal, mira esto SO here, o ejecutarlo desde un hilo con un bucle de ejecución activo, marque este SO here, de la documentación de 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. 

Asegúrese de que su locationController y CCLocationManager en su interior estén vivos después de la inicialización, marque here. Puede que me equivoque aquí, pero a partir de su código de Github, parece que la variable *lc se está liberando en el grupo de liberación automática. Intenta darle un retener extra.

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

Supongo que esta es la causa de su problema. Si el objeto se lanza, no obtendrás ninguna actualización.

no relacionado con la pregunta, pero:

usted debe llamar [super dealloc] por último, pero no en primer lugar, comprobar esto SO here

colocar la instrucción de retorno en el método init antes del último paréntesis, y no antes de la segunda último.

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

     } 
    } 
    return self; 
} 
+0

Lo intenté y actualicé el código en github. En la consola en xcode no veo aparecer ningún encabezado, sin embargo recibí un error que no había visto antes: '13 de septiembre 13:00 : 44 CommCenter desconocido [56] : kDataAttachStatusNotification enviado, wasAttached: 1 isAttached: 1' – Vikko

+0

después de combinar su respuesta con 'performSelectorOnMainThread' funcionó !! Gracias por su ayuda, he estado atascado en esto durante aproximadamente 7 semanas:) Puedes imaginar lo feliz que estoy de poder continuar mi desarrollo ahora. Código de trabajo actualizado @ github – Vikko

+0

Tuve el problema de que también estaba en otro hilo. Me da miedo pensar cuánto tiempo me hubiera llevado averiguarlo sin tu respuesta, ¡así que muchas gracias! – poshaughnessy

0
- (void)locationManager:(CLLocationManager *)manager 
didUpdateHeading:(CLHeading *)heading; 
- (void)locationManager:(CLLocationManager *)manager 
didFailWithError:(NSError *)error; 

Estos son sus métodos de instancia no delegar métodos.

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

+3

La pregunta es para iOS (que tiene un método de delegado didUpdateHeading). Su enlace apunta a la documentación de OS X. – Anna

0

Posiblemente esto no es la solución al problema global, pero su método de init le falta una instrucción de retorno:

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

    return self; 
} 
+0

He estado jugando con muchas formas de inicialización y olvidé volver a ponerlo: P Aunque no resuelve nada, debería estar allí, ¡gracias por el informe! – Vikko

+0

También creo que el problema es con su [init]. a partir de los fragmentos de código, debe establecer explícitamente *** self = [super init] ***, ya que el auto no está listo aún, a menos que lo haga como se sugirió tilo, if (self = [super init]) {.. .}. ¡buena suerte! – dklt

+0

Intenté esto y no hay solución, lástima :( – Vikko

Cuestiones relacionadas