3

I am using CLLocationManager on device and the delegate methods aren't getting called. Here's my code (I can see that the class isn't getting deallocated either):

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

@interface CurrentLocation : NSObject <CLLocationManagerDelegate> {
    CLLocationManager *locationManager;

}
@property (nonatomic, retain) CLLocationManager *locationManager;  

@end

#import "CurrentLocation.h"
#import "SBJson.h"
@implementation CurrentLocation
@synthesize locationManager;

- (id)init
{
    self = [super init];
    if (self) {
        NSLog(@"Initialized");
        locationManager = [[[CLLocationManager alloc] init] autorelease];
        locationManager.delegate = self;
        [locationManager startUpdatingLocation];
        BOOL enable = [CLLocationManager locationServicesEnabled];
        NSLog(@"%@", enable? @"Enabled" : @"Not Enabled");
    }

    return self;
}

- (void)locationManager:(CLLocationManager *)manager
    didUpdateToLocation:(CLLocation *)newLocation
           fromLocation:(CLLocation *)oldLocation {
    NSLog(@"A");
    NSString *stringURL = [NSString stringWithFormat:@"http://maps.googleapis.com/maps/api/geocode/json?latlng=%f,%f&sensor=true", newLocation.coordinate.latitude, newLocation.coordinate.longitude];
    NSLog(@"%@", stringURL);

    NSURL *url = [NSURL URLWithString:stringURL];

    NSData *data = [NSURLConnection sendSynchronousRequest:[NSURLRequest requestWithURL:url] returningResponse:nil error:nil];

    SBJsonParser *parser = [[SBJsonParser alloc] init];
    NSDictionary *dict = [parser objectWithData:data];
    NSLog(@"%@", dict);
}

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

- (void)dealloc {
    NSLog(@"Dealloc called");
    [super dealloc];
    [locationManager release];
}

@end

In log, I see:

2011-10-02 19:49:04.095 DixieMatTracker[1404:707] Initialized
2011-10-02 19:49:04.109 DixieMatTracker[1404:707] Enabled

What am I doing wrong? Thanks

0xSina
  • 20,973
  • 34
  • 136
  • 253
  • How is the `locationManager` property defined? –  Oct 02 '11 at 23:55
  • Unlikely to make a difference, but I've seen stranger things. Put self.locationManager (to access property). Without self, it accesses backing variable, without retaining (as you have autoreleased). – Daryl Teo Oct 03 '11 at 00:00
  • 1
    @PragmaOnce Is it `assign`, `retain`, what? Try using `self.locationManager` instead. @Daryl Teo I agree, this is likely the problem as `locationManager` will be autoreleased. –  Oct 03 '11 at 00:03
  • `[super dealloc]` should be called at the end of your custom `dealloc` implementation, not first. – Leslie Godwin Sep 01 '15 at 10:14

3 Answers3

6

You're using the locationManager ivar, not the property; this means that the CLLocationManager isn't being retained and will be deallocated as you're autoreleasing it. Use self.locationManager:

self.locationManager = [[[CLLocationManager alloc] init] autorelease];
3

I would suggest that you check your memory management on your CLLocationManager instance.

Write it so:

#import "CurrentLocation.h"
#import "SBJson.h"
@implementation CurrentLocation
@synthesize locationManager;

- (id)init
{
    self = [super init];
    if (self) {
        NSLog(@"Initialized");
        locationManager = [[CLLocationManager alloc] init];
        locationManager.delegate = self;
        [locationManager startUpdatingLocation];
        BOOL enable = [CLLocationManager locationServicesEnabled];
        NSLog(@"%@", enable? @"Enabled" : @"Not Enabled");
    }

    return self;
}

- (void)locationManager:(CLLocationManager *)manager
    didUpdateToLocation:(CLLocation *)newLocation
           fromLocation:(CLLocation *)oldLocation {
    NSLog(@"A");
    NSString *stringURL = [NSString stringWithFormat:@"http://maps.googleapis.com/maps/api/geocode/json?latlng=%f,%f&sensor=true", newLocation.coordinate.latitude, newLocation.coordinate.longitude];
    NSLog(@"%@", stringURL);

    NSURL *url = [NSURL URLWithString:stringURL];

    NSData *data = [NSURLConnection sendSynchronousRequest:[NSURLRequest requestWithURL:url] returningResponse:nil error:nil];

    SBJsonParser *parser = [[SBJsonParser alloc] init];
    NSDictionary *dict = [parser objectWithData:data];
    NSLog(@"%@", dict);
}

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

- (void)dealloc {
    NSLog(@"Dealloc called");
    [super dealloc];
    [locationManager release];
}

@end

The delegate does not get called because the CLLocationManager object is deallocated before it can provide a response to the location request. This is caused by the autorelease in your code.

Besides that - iff autorelease is used it would be a mistake to manually release it in dealloc. This could lead to unexpected crashes.

The solution above does it 'by-hand' allocating a CLLocationManager in init and releasing it in dealloc.

Wizz
  • 1,267
  • 1
  • 13
  • 20
  • Wow. that worked. Still don't understand why the CLLocationManager instance was deallocated...I am autoreleasing and then using the accuser to retain it. Anyways, thanks a lot. – 0xSina Oct 03 '11 at 00:04
  • 1
    This doesn't solve the underlying problem: the property isn't being used. –  Oct 03 '11 at 00:11
  • Use of the property was not asked.. BTW this is exactly what happens if the property was defined as retain and has been properly accessed using self.locationManager – Wizz Oct 03 '11 at 00:15
0

In my case it was because of my device was unable to determine location - while staying indoors GPS signal was unavailable and wi-fi was also disconnected so location manager just wasn't able to receive any location data and delegate was never called.

Once I've connected wi-fi it worked (I guess moving outdoors should also do the trick in that case, but sometimes it is not very convenient way :) )

vir us
  • 9,920
  • 6
  • 57
  • 66