I keep getting this error which indicates a Zombie. I've narrowed it down to these two methods, but I can't for the life of me figure out what's wrong.
Any ideas?
-(void) getWeatherDetail: (NSString *)query
{
@try
{
NSString *urlString111 = [NSString stringWithFormat:@"http://www.google.com/ig/api?weather=%@",query];
urlString111 = [urlString111 stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *url = [NSURL URLWithString:urlString111];
NSMutableURLRequest *theRequest = [NSMutableURLRequest requestWithURL:url];
NSData *returnData = [NSURLConnection sendSynchronousRequest:theRequest returningResponse:nil error:nil];
if(xmlParser)
{
xmlParser=nil;
[xmlParser release];
}
xmlParser = [[NSXMLParser alloc] initWithData: returnData];
isForeCast = NO;
isFirstForeCastEnd = NO;
if (!self.arrForecastAll) {
self.arrForecastAll = [[NSMutableArray alloc] init];
}
[self.arrForecastAll removeAllObjects];
[xmlParser setDelegate: self];
[xmlParser setShouldResolveExternalEntities: YES];
[xmlParser parse];
// self.logString = [NSString stringWithFormat:@"%@Date & Time: %@ | Text: Getting Weather detail.\n", self.logString, [NSDate date]];
// [self updateLogFile:self.logString];
}
@catch (NSException *exception) {
NSLog(@"Ad exc %@",[exception description]);
}
@finally {
}
}
And this one..
-(void)getCurrentCityName
{
//////Method to find current city name
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
@try
{
if ([self.arrSettings count] > 0 && [[[self.arrSettings objectAtIndex:3] objectForKey:@"Value"] isEqualToString:@"Current Location"])
{
if (currentlat != 0 && currentlong != 0) {
NSURL *urlString;
NSLog(@"lat %f %f" ,currentlat,currentlong);
urlString =[NSURL URLWithString:[NSString stringWithFormat:@"http://maps.google.com/maps/geo?output=json&oe=utf-8&ll=%f,%f&key=[removed API key]",currentlat,currentlong]];
NSLog(@"\n\n-------------------------TF-Get City Name -Request-----------------------------\n%@\n\n",urlString);
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init] ;
[request setURL:urlString];
NSData *returnData = [ NSURLConnection sendSynchronousRequest: request returningResponse:nil error: nil ];
NSString *returnString = [[NSString alloc] initWithData:returnData encoding:NSUTF8StringEncoding];
NSLog(@"\n\n------------------------TF-Get City Name -Response------------------------\n\n%@\n\n",returnString);
[request release];
NSDictionary *dictAddress=[returnString objectFromJSONString];
NSLog(@"dictAddress %@",[dictAddress description]);
[returnString release];
NSString *strCity = [NSString stringWithFormat:@"Getting Location"];
NSLog(@"strCity %@",strCity);
if ([[dictAddress allKeys] count] > 1)
{
if ([[[[[[dictAddress valueForKey:@"Placemark"] objectAtIndex:0] valueForKey:@"AddressDetails"] valueForKey:@"Country"] valueForKey:@"AdministrativeArea"] valueForKey:@"SubAdministrativeArea"])
{
strCity = [NSString stringWithFormat:@"%@,%@",
[[[[[[[[dictAddress valueForKey:@"Placemark"] objectAtIndex:0] valueForKey:@"AddressDetails"] valueForKey:@"Country"] valueForKey:@"AdministrativeArea"] valueForKey:@"SubAdministrativeArea"] valueForKey:@"Locality"] valueForKey:@"LocalityName"],
[[[[[[dictAddress valueForKey:@"Placemark"] objectAtIndex:0] valueForKey:@"AddressDetails"] valueForKey:@"Country"] valueForKey:@"AdministrativeArea"] valueForKey:@"AdministrativeAreaName"]];
}
else {
strCity = [NSString stringWithFormat:@"%@,%@",
[[[[[[[dictAddress valueForKey:@"Placemark"] objectAtIndex:0] valueForKey:@"AddressDetails"] valueForKey:@"Country"] valueForKey:@"AdministrativeArea"] valueForKey:@"Locality"] valueForKey:@"LocalityName"],
[[[[[[dictAddress valueForKey:@"Placemark"] objectAtIndex:0] valueForKey:@"AddressDetails"] valueForKey:@"Country"] valueForKey:@"AdministrativeArea"] valueForKey:@"AdministrativeAreaName"]];
}
self.strCurrentCity = strCity;
[self getWeatherDetail:self.strCurrentCity];
}
}
else
{
self.strCurrentCity = @"Current Location";
}
}
else
{
self.strCurrentCity = [[self.arrSettings objectAtIndex:3] objectForKey:@"Value"];
[self getWeatherDetail:self.strCurrentCity];
}
// self.logString = [NSString stringWithFormat:@"%@Date & Time: %@ | Text: Getting current city name. CityName: %@\n", self.logString, [NSDate date], self.strCurrentCity];
// [self updateLogFile:self.logString];
[pool release];
}
@catch (NSException *exception) {
NSLog(@"Ad exc %@",[exception description]);
}
@finally {
}
}
This is the classic memory-management problem that you get by direct ivar access. Use accessors to deal with your ivars, and your code will be simpler and you won't have these kinds of bugs.
So replace this code:
if(xmlParser)
{
xmlParser=nil;
[xmlParser release];
}
xmlParser = [[NSXMLParser alloc] initWithData: returnData];
isForeCast = NO;
isFirstForeCastEnd = NO;
if (!self.arrForecastAll) {
self.arrForecastAll = [[NSMutableArray alloc] init];
}
with:
self.xmlParser = [[[NSXMLParser alloc] initWithData: returnData] autorelease];
self.isForeCast = NO;
self.isFirstCoreCastEnd = NO;
if (!self.arrForecastAll) {
self.arrForecastAll = [NSMutableArray array];
}
This also removes the leak in your assignment to arrForecastAll
.
Regarding your second block, any time you release
a variable, you should always set it to nil
if the variable is not immediately going out of scope. So for instance, you [request release]
should be followed by request = nil
.
BTW, why are you putting all of this in a @try block? Exception handling in ObjC is rare, expensive, and leaks memory. Exceptions generally indicate unrecoverable errors in ObjC and are not a general error-handling system. There are times when @try is appropriate, but I don't see any reason here.