Hello all ,
I am using the location manager to generate location data that I send in a URL to down load data. The first time I call the location manager, it correctly returns the current location and based on the current location I can fetch the data from the URL.
However, when I attempt to retrieve the current location a second time, I receive a EXC_BAD_EXCESS.
When I try debugging with NSZombieEnabled
it shows me FirstViewController.recievedData
as a zombie in the didReceiveResponse
method. (see marked code below)
I dug further and I found that after releasing the initial connection an unknown connection is established and then it tries to access receivedData
which is already released .
The header file info :`
#import <CoreLocation/CoreLocation.h>
define SECS_OLD_MAX 1
@interface FirstViewController : UIViewController<CLLocationManagerDelegate> {
UIActivityIndicatorView *spinner;
CLLocationManager *locationManager;
CLLocation *startingPoint;
UIButton *relocateMe;
NSMutableData *receivedData;
NSString *lat;
NSString *lon;
}
@property (nonatomic, retain) IBOutlet UIActivityIndicatorView *spinner;
@property (nonatomic, retain) CLLocationManager *locationManager;
@property (nonatomic, retain) CLLocation *startingPoint;
@property (nonatomic, retain) IBOutlet UIButton *relocateMe;
@property (nonatomic, retain) NSMutableData *receivedData;
@property (nonatomic, retain) NSString *lat;
@property (nonatomic, retain) NSString *lon;
`
The .m file code :
//starting the manger :
[spinner startAnimating];
**EDIT**************************ADDED IN THE AUTORELEASE POOL BY HIB********************************
self.locationManager = [[[CLLocationManager alloc] init]autorelease];
// Detecting the user device
NSString *currentDevice = [[UIDevice currentDevice] model];
// if its iPhone then locate the current lattitude and longitude
if([currentDevice isEqualToString:@"iPhone"] || [currentDevice isEqualToString:@"iPhone 3G"] || [currentDevice isEqualToString:@"iPhone 3G S"]){
DLog(@"I have identified the device as an iPhone");
if(locationManager.locationServicesEnabled == YES){
DLog(@"ok now the location manager gets the property");
locationManager.delegate = self;
// This is the most important property to set for the manager. It ultimately determines how the manager will
// attempt to acquire location and thus, the amount of power that will be consumed.
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
// Once configured, the location manager must be "started".
[locationManager startUpdatingLocation] ;
}else {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Oops!"
message:@"Please enable location servies"
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alert show];
[alert release];
}
}
//if its iPod then fetch the city based restaurants
else if([currentDevice isEqualToString:@"iPod touch"] || [currentDevice isEqualToString:@"iPod touch 2G"]){
}
else if([currentDevice isEqualToString:@"iPhone Simulator"]){
//TechZen says: there appears to be some code missing here, not sure if its relevant
}
//didupdatetolocation method
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation {
// store the location as the "best effort"
DLog(@"Lat = %g Long = %g",newLocation.coordinate.latitude,newLocation.coordinate.longitude);
NSDate *eventDate = newLocation.timestamp;
NSTimeInterval howRecent = [eventDate timeIntervalSinceNow];
DLog(@"NSTIME INTERVAL = %i",howRecent);
//Is the event recent and accurate enough ?
if (abs(howRecent) < SECS_OLD_MAX) {
self.lat = [NSString stringWithFormat:@"%g",newLocation.coordinate.latitude];
self.lon = [NSString stringWithFormat:@"%g",newLocation.coordinate.longitude];
[[NSUserDefaults standardUserDefaults] setObject:lat forKey:@"LATITUDE"];
[[NSUserDefaults standardUserDefaults] setObject:lon forKey:@"LONGITUDE"];
DLog(@"inside Lat = %g Long = %g",newLocation.coordinate.latitude,newLocation.coordinate.longitude);
self.startingPoint = newLocation;
[locationManager stopUpdatingLocation];
**EDIT********************************REMOVED BY HIB******************************
self.locationManager = nil;
[locationManager release];
**EDIT********************************REMOVED BY HIB******************************
**ADDED BY HIB********************************************
locationManager.delegate = nil;
**ADDED BY HIB********************************************
@try {
//passing the parameter for more condition
self.lat = [NSString stringWithFormat:@"%g",startingPoint.coordinate.latitude];
self.lon = [NSString stringWithFormat:@"%g", startingPoint.coordinate.longitude];
NSString *string2 = [[NSString alloc] initWithFormat:@"%@/Service.asmx/someMethod?lat1=%g&lon1=%g&recordSize=0"
,[[NSUserDefaults standardUserDefaults] stringForKey:@"textEntry_key"],startingPoint.coordinate.latitude,startingPoint.coordinate.longitude];
NSURL *url = [[NSURL alloc] initWithString:string2];
[string2 release];
NSMutableURLRequest* request2=[NSMutableURLRequest requestWithURL:url];
[request2 setHTTPMethod:@"GET"];
[request2 setTimeoutInterval:25.0];
[[NSURLCache sharedURLCache] setMemoryCapacity:0];
[[NSURLCache sharedURLCache] setDiskCapacity:0];
NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:request2 delegate:self];
if (theConnection) {
receivedData = [[NSMutableData data]retain];
} else {
// inform the user that the download could not be made
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Sorry !"
message:@"The server is not avaialable \n Please try againa later"
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alert show];
[spinner stopAnimating];
}
[url release];
}
@catch (NSException * e) {
}
@finally {
}
}
}
//and the delegate methods
#pragma mark -
#pragma mark connection methods
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
// this method is called when the server has determined that it
// has enough information to create the NSURLResponse
// it can be called multiple times, for example in the case of a
// redirect, so each time we reset the data.
// receivedData is declared as a method instance elsewhere
**************************************the zombie is here *********************************
[receivedData setLength:0];
*****************************************************************************************
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
// append the new data to the receivedData
// receivedData is declared as a method instance elsewhere
[receivedData appendData:data];
}
- (void)connection:(NSURLConnection *)connection
didFailWithError:(NSError *)error
{
[spinner stopAnimating];
// release the connection, and the data object
[connection release];
// receivedData is declared as a method instance elsewhere
[receivedData release];
// inform the user
DLog(@"Connection failed! Error - %@ %@",
[error localizedDescription],
[[error userInfo] objectForKey:NSErrorFailingURLStringKey]);
// alert the user in the inter face.
UIAlertView* alert = [[UIAlertView alloc]initWithTitle:@"Sorry !"
message:@"The server is not available.\n Please try again later."
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alert show];
[alert release];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
// do something with the data
// receivedData is declared as a method instance elsewhere
DLog(@"Succeeded! Received %d bytes of data",[receivedData length]);
[spinner stopAnimating];
// release the connection, and the data object
if(receivedData == nil)
{
UIAlertView* alert = [[UIAlertView alloc]initWithTitle:@"Sorry !"
message:@"The server is not available.\n Please try again later or select city."
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alert show];
[alert release];
[spinner stopAnimating];
}
else
{
//just parse and use the data
}
[connection release];
[receivedData release];
}
Please help . I am stuck.