Can anyone identify the leakage , help?
-
16-09-2019 - |
Question
I have developed my iPhone application and now I am testing it with instruments to find memory leakages .
I have my appDelegate class in which I am fetching data from web service and then parse it then store it in an array..
Here is my applicationDidFinishLaunching method :
UIApplication* app = [UIApplication sharedApplication];
app.networkActivityIndicatorVisible = YES;
serviceURL = [[NSUserDefaults standardUserDefaults] stringForKey:@"readOnly_key"];
NSLog(@"text = %@",serviceURL);
if(serviceURL == nil)
{
//We set the default values from the settings bundle.
//Get the bundle path
NSString *bPath = [[NSBundle mainBundle] bundlePath];
NSString *settingsPath = [bPath stringByAppendingPathComponent:@"Settings.bundle"];
NSString *plistFile = [settingsPath stringByAppendingPathComponent:@"Root.plist"];
NSDictionary *settingsDictionary = [NSDictionary dictionaryWithContentsOfFile:plistFile];
NSArray *preferencesArray = [settingsDictionary objectForKey:@"PreferenceSpecifiers"];
NSDictionary *item;
NSString *textEntry_Key;
NSString *readOnly_Key;
for(item in preferencesArray)
{
//Get the key of the item.
NSString *keyValue = [item objectForKey:@"Key"];
//Get the default value specified in the plist file.
id defaultValue = [item objectForKey:@"DefaultValue"];
if([keyValue isEqualToString:@"textEntry_key"]){
textEntry_Key = defaultValue;
}
NSLog(@"default value = %@",defaultValue);
if([keyValue isEqualToString:@"readOnly_key"])
readOnly_Key = defaultValue;
}
//Now that we have all the default values.
//We will create it here.
NSDictionary *appPrerfs = [NSDictionary dictionaryWithObjectsAndKeys:
textEntry_Key, @"textEntry_key",
readOnly_Key, @"readOnly_key",
nil];
[[NSUserDefaults standardUserDefaults] registerDefaults:appPrerfs];
[[NSUserDefaults standardUserDefaults] synchronize];
}
NSURL *url5 = [[NSURL alloc] initWithString:@"http://192.168.0.150/Nirmal/Service.asmx/searchParameterList"];
//NSURL *url5 = [[NSURL alloc] initWithString:[NSString stringWithFormat:@"%@/Service.asmx/searchParameterList"]];
NSMutableURLRequest* request6=[NSMutableURLRequest requestWithURL:url5];
[request6 setHTTPMethod:@"POST"];
[request6 setTimeoutInterval:10];
//NSURLResponse *response6=nil;
// NSError *err6=nil;
//NSData *data6=[[NSURLConnection sendSynchronousRequest:request6 returningResponse:&response6 error:&err6] retain];
data2=[NSURLConnection sendSynchronousRequest:request6 returningResponse:nil error:nil];
if(data2 == nil)
{
UIAlertView* alert = [[UIAlertView alloc]initWithTitle:@"Alert" message:@"The network is not available.\n Please check the Internet connection." delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alert show];
[alert release];
}
else
{
NSXMLParser *xmlParser5 = [[NSXMLParser alloc] initWithData:data2];
//Initialize the delegate.
SearchParameterDataParser *searchParameterDataParser = [[SearchParameterDataParser alloc] initSearchParameterDataParser];
//Set delegate
[xmlParser5 setDelegate:searchParameterDataParser];
//Start parsing the XML file.
@try {
// **the leakage line**
BOOL success1 = [xmlParser5 parse];
if(success1)
NSLog(@"No Errors");
else
NSLog(@"Error Error Error!!!");
}
@catch (NSException * e) {
NSLog(@"Exception in parsing %@ %@",[e name], [e reason]);
}
//[xmlParser5 release];
[searchParameterDataParser release];
//[xmlParser5 release]; //leakage
}
[data2 release];
and this is my parser class :
#import "SearchParameterDataParser.h"
#import "AppDelegate.h"
#import "SearchClass.h"
@implementation SearchParameterDataParser
-(SearchParameterDataParser *)initSearchParameterDataParser{
[super init];
appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
return self;
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName
attributes:(NSDictionary *)attributeDict {
if([elementName isEqualToString:@"SearchClass"]) {
[appDelegate.tempArray release];
appDelegate.tempArray = [[NSMutableArray alloc] init];
appDelegate.aSearchClass = [[SearchClass alloc]init];
}
NSLog(@"Processing Element: %@", elementName);
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
if(!currentElementValue){
[currentElementValue release];
currentElementValue = [[NSMutableString alloc] initWithString:string];
}
else
[currentElementValue appendString:string];
NSLog(@"Processing Value: %@", currentElementValue);
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
if([elementName isEqualToString:@"SearchClass"]){
[appDelegate.tempArray addObject:appDelegate.aSearchClass];
return;
}
else
[appDelegate.aSearchClass setValue:currentElementValue forKey:elementName];
// [currentElementValue release];
currentElementValue = nil;
}
- (void) dealloc {
[super dealloc];
[aSearchClass release];
[currentElementValue release];
//[self release];
}
@end
I have specified the leakage line in the code .
Can anyone tell me what is going wrong or how can I solve the memory leakage ???????
Solution
This is pretty messy, as a suggestion to clean things up a bit, try moving some memory management stuff to accessor methods - your code is littered with -release methods. ie,
instead of:-
if([elementName isEqualToString:@"SearchClass"]) {
[appDelegate.tempArray release];
appDelegate.tempArray = [[NSMutableArray alloc] init];
}
try:-
if([elementName isEqualToString:@"SearchClass"]) {
appDelegate.tempArray = [NSMutableArray array];
}
where
appDelegate has a method
- (void)setTempArray:(NSMutableArray *)value {
if(value!=tempArray){
[tempArray release];
tempArray = [value retain];
}
}
or you can use a @synthesized accessor method to save coding it yourself. As an aside tempArray is a terrible name for an instance variable. Also note that you are releasing the old tempArray each time you make a new one - when does the last instance get cleaned up?
This is still not great as your parser class should not access directly the instance variables in appDelegate. Vardiables tempArray and searchClass should be private, but that is off the point and more of a design issue.
Where does url5 get released?
What is this supposed to do?
if(!currentElementValue){
[currentElementValue release];
}
release currentElementValue if it doesn't exist?
[data2 release];
Did you retain data2?
- (void) dealloc {
[super dealloc];
[aSearchClass release];
[currentElementValue release];
//[self release];
}
i thought aSearchClass was an instance variable on appDelegate?
This might sound like nitpicking but it is much easier to track down leaks if make your code clear and you know exactly what is going on.
OTHER TIPS
You need to release both url5
and xmlParser5
, since you've allocated them using alloc
.
You should also be wary of calling release
on properties, since the standard setters created when you @synthesize
an instance variable typically release the previous value of the variable before setting the new value.