2011-05-10 8 views
6

Hola, estoy jugando con las ubicaciones en el iPhone y desde el principio me encontré con problemas. He localizado mi problema y determiné que es CLLocationManager lo que me está molestando.CLLocationManager nunca llama a los métodos de delegado

Así que desarrollaron aplicación muy sencilla. Solo tengo un controlador de vista con un CLLocationManager en él. A la vista cargué, inicialicé CLLocationManager y comencé a actualizar. También implementé dos métodos, didFailWithError y didUpdateToLocation.

He leído un montón de preguntas y lo que he aprendido hasta tarifa es esto. Debe retener CLLocationManager durante la inicialización. También es aconsejable establecer CLLocationManagersdelegate a nil durante la descarga de un view (algo que ver con los mensajes que pasan a CLLocationManager porque marco conserva y nunca es liberar adecuadamente)

en resumen, simplemente no puedo encontrar una explicación decente en lo que a hacer y cómo hacerlo funcionar

Aquí está mi código de modo que si alguien podía entenderlo lo agradecería. viewControllers archivo de cabecera

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

@interface CoreLocationViewController : UIViewController <CLLocationManagerDelegate> 
{ 
    CLLocationManager *locManager; 
} 

@property (nonatomic, retain) CLLocationManager *locManager; 

@end 

archivo .m viewController

#import "CoreLocationViewController.h" 


@implementation CoreLocationViewController 
@synthesize locManager; 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

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

    self.view.backgroundColor = [UIColor grayColor]; 
} 

#pragma mark - 
#pragma mark Location Delegate 

- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error 
{ 
     NSLog(@"in fail with error"); 
} 

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation 
{ 
    NSLog(@"in update to location"); 
} 


#pragma mark - 
#pragma mark Memory Management 

- (void)didReceiveMemoryWarning { 
    [super didReceiveMemoryWarning]; 
} 

- (void)viewDidUnload 
{ 
self.locManager.delegate = nil; 
    [super viewDidUnload]; 
} 


- (void)dealloc 
{ 
    [locManager release]; 
     [super dealloc]; 
} 


@end 

Por cierto: estoy usando iOS 4.2. Estoy señalar esto porque he leído que Apple ha cambiado delegados ubicación en IOS 4

+2

Se está filtrando aquí, porque self.locManager = [[CLLocationManager alloc] init]; está reteniendo el objeto sobre el recuento de ref que se obtiene al usar alloc init. – logancautrell

Respuesta

3

Así que logré encontrar un error. Fue en la gestión de la memoria. En mi archivo de delegado de aplicación, inicié un CoreLocationViewController y lo agregué como subview a mi ventana, después de eso lo lancé y todo está bien. Pero, la parte de lanzamiento no era una buena forma de hacerlo. Después de que lancé mi ViewController, se llama al método dealloc y se libera locationManager.

Así que lo correcto es no lanzar un ViewController que contenga locationManager, o encuentre otra forma de solucionarlo. No estoy muy seguro de por qué eso fue un problema porque pensé que después de agregar un ViewController a una ventana se conserva, por lo tanto, también se retiene su localtionManager. Si alguien puede aclararlo, sería muy apreciado.

+0

No. Después de agregar la vista de un controlador de vista a una ventana, se conserva su VISTA, pero no la vista en sí. Esta es una publicación anterior, pero aún vale la pena comentarla. Liberar un controlador de vista que está en la pantalla probablemente causará un bloqueo cuando algo que sucede (como un toque de botón) intente llamar a uno de los métodos del controlador de vista. –

0

Idk si se trata de una cuestión, pero en mi código que también configurar la precisión deseada

[locManager setDesiredAccuracy: kCLLocationAccuracyBest];

Por ejemplo.

2

¿Está probando en el dispositivo? ¿están habilitados los servicios de localización?

if (self.locManager.locationServicesEnabled){ 
//do domething 
} 
+0

lo intenté .. utilicé 'if ([CLLocationManager locationServicesEnabled]) { \t [self.locManager startUpdatingLocation]; } ' pero no sirvió de nada. Creo que hay algo más en él. – paxx

+0

¿El framework de ubicación de colas definitivamente se ha agregado a tu compilación? –

+1

sí ... no funcionaría sin – paxx

3

esto puede ser poco quisquilloso pero en cambio viewDidLoad:

locManager.delegate = self; 

a:

self.locManager.delegate = self; 

no sé si va a arreglar, pero es mejor que ser coherente .

+1

tnx, pero no ayudó .. – paxx

+0

Esta corrección funciona para mí. – heMac

0

Prueba esto:

NSLog(@"location services enabled: %d", [locManager locationServicesEnabled]); 

A partir de los documentos:

El usuario puede activar o desactivar los servicios de localización por completo de la aplicación de ajustes moviendo el interruptor en Ajustes> General> Servicios de Localización.

+0

lo intenté .. utilicé 'if ([CLLocationManager locationServicesEnabled]) { \t [self.locManager startUpdatingLocation]; } ' pero no sirvió de nada. Creo que hay algo más en eso – paxx

+0

¿Qué dice la declaración de NSLog? ¿Están habilitados o no sus servicios loc? La instrucción if no les habilitará si están deshabilitados; debe hacer eso en la aplicación de Configuración. – Rayfleck

+0

servicio está habilitado .. pero estoy ejecutando en el simulador, y no estoy seguro de que se ejecute en simulador llame a cualquiera de los delegados ... supongo que al menos debería llamar error delegado – paxx

4

Otros carteles han mencionado la comprobación de autorización, y definitivamente debe agregar eso, pero no creo que ese sea su problema. Si no está autorizado, se llamará a su método didFailWithError:. Esto lleva a creer que algo más está sucediendo aquí.

Puede ser una buena idea asegurarse de que se esté asignando su administrador de ubicación y mientras lo hace puede solucionar su pérdida de memoria.

Prueba esto:

CLLocationManager* lm = [[CLLocationManager alloc] init]; 
NSAssert(lm != nil, @"Failed to allocate CLLocation manage"); 
self.locManager = lm; 
[lm release]; 
self.locManager.delegate = self; 
[self.locManager startUpdatingLocation]; 
// Let's just print what we got 
NSLog(@"CLLocationManager is %@", lm); 

Si el plazo esto su recibirá uno de los siguientes resultados:

1) Si el gerente de locación vuelve nula, su programa se colgará en el depurador (porque de NSAssert)

2) si se imprime "CLLocationManager is ...." y todavía no ve actualizaciones, entonces tiene un verdadero misterio en sus manos.

3) No se imprime nada. Eso podría significar, tal vez debido a algo vinculado incorrectamente en Interface Builder, que viewDidLoad no se está llamando en absoluto.

4) Recibirá una llamada didFailWithError: porque no está autorizado. Lo que significa que al menos todo está funcionando como se esperaba.

Como un lado, tenía una pérdida de memoria porque estaba asignando el resultado de una asignación directamente a una propiedad con el atributo retain. Después de asignar, su conteo sería +1 después de la asignación, sería +2, por lo que si la vista se descargara y se volviera a cargar, se produciría una fuga.

Espero que algo de esto ayude.

+0

lo intenté ... y tengo un CLLocationManager sospechoso es ... creo que hay algo más ... tal vez locationFramework en mi computadora no está instalado correctamente ... ¿sabe de algún proyecto, o lo hace? tener y proyecto que usa locationManager y funciona al 100% .. quiero probar si es mi código o tal vez algo más ... btw: tnx para alloc thing ... no sabía eso ... solía ser un codificador .NET así que estoy Todavía estoy tratando de adaptarme al entorno del recolector de basura – paxx

+0

Estoy usando un simulador porque no tengo mis propios desarrolladores, pero voy a probarlo con mis amigos hoy para ver qué pasa en el dispositivo ... pero yo ' Estoy confundido en una cosa ... ¿no debería al menos llamar a un delegado de error en el simulador? ¿o es normal que en el simulador no ocurra nada? – paxx

+0

@paki En mi versión del simulador, 4.2, se ejecuta correctamente (aunque solo se reciben algunas actualizaciones). No recuerdo lo que sucedió en versiones anteriores. – idz

0

Tengo el mismo problema y, como dijo paxx, es un problema de gestión de memoria. Mi solución es retener 'yo' manualmente. Como muestra el código a continuación:

- (void) viewDidload 
{ 
    [super viewDidload]; 
    if (![CLLocationManager locationServicesEnabled]) { 
     NSLog(@"Location Service Disabled!"); 
    } else { 
     [self retain]; 
     //initialize the cllocationmanager obj. 
    } 
} 


-(void)locationManager:(CLLocationManager *)manager 
    didUpdateLocations:(NSArray *)locations 
{ 
    //do your surf 
    [self release]; 
} 


-(void)locationManager:(CLLocationManager *)manager 
    didUpdateToLocation:(CLLocation *)newLocation 
      fromLocation:(CLLocation *)oldLocation 
{ 
    //do your stuff 
    [self release]; 
} 

-(void)locationManager:(CLLocationManager *)manager 
     didFailWithError:(NSError *)error 
{ 
    //do your stuff 
    [self release]; 
} 

No es bonita, pero funciona bien para mí.

17

En mi caso, el delegado no se llama a causa de un problema de roscado

  • el hilo que opera LocationManager debe tener un NSRunLoop establece hasta
  • si utiliza hilo principal, que ya tienen un runloop, ahora sólo necesario crear una instancia del gestor y utilizarlo en hilo principal

Read this to know more about CLLocationManagerDelegate

+0

Perfecto. Me lo arregló Ya probé esto antes, pero solo lo aseguré para el método 'startUpdatingLocation'. ¡En realidad, alloc/init, etc. tiene que estar en el hilo principal también! –

+0

¡La respuesta! La instanciación de CLLocationManager en una cola separada del hilo principal fue mi problema. El envío de la llamada al hilo principal lo solucionó. – jcady

+0

@TimBodeit Esto ciertamente solucionó el problema para mí. Pero lo que no entiendo es que anteriormente lo llamaba desde 'viewDidLoad'. ¿No se ejecuta 'viewDidLoad' desde el hilo principal? – Honey

8

Además, en iOS8 debe tener dos cosas adicionales:

  • agregar una clave a su Info.plist y solicitar la autorización del gerente de locación pidiendo que se inicie.

    • NSLocationWhenInUseUsageDescription

    • NSLocationAlwaysUsageDescription

  • necesita solicitar autorización para el método de localización correspondiente.

    • [self.locationManager requestWhenInUseAuthorization]

    • [self.locationManager requestAlwaysAuthorization]

Código ejemplo:

self.locationManager = [[CLLocationManager alloc] init]; 
self.locationManager.delegate = self; 
// Check for iOS 8. Without this guard the code will crash with "unknown selector" on iOS 7. 
if ([self.locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]) { 
    [self.locationManager requestWhenInUseAuthorization]; 
} 
[self.locationManager startUpdatingLocation]; 

Fuente: http://nevan.net/2014/09/core-location-manager-changes-in-ios-8/

Cuestiones relacionadas