我开发了我的iPhone应用程序,现在我正在用仪器测试它以找到内存泄漏。
我有我的appDelegate类,我在其中从Web服务获取数据,然后解析它然后将其存储在数组中..
这是我的applicationDidFinishLaunching方法:
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];
这是我的解析器类:
#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
我在代码中指定了泄漏线。
任何人都可以告诉我出了什么问题或者如何解决内存泄漏????????
答案 0 :(得分:3)
这是非常混乱的,作为一个清理一点的建议,尝试将一些内存管理的东西移动到访问器方法 - 你的代码充满了-release方法。即,
而不是: -
if([elementName isEqualToString:@"SearchClass"]) {
[appDelegate.tempArray release];
appDelegate.tempArray = [[NSMutableArray alloc] init];
}
尝试: -
if([elementName isEqualToString:@"SearchClass"]) {
appDelegate.tempArray = [NSMutableArray array];
}
其中
appDelegate有一个方法
- (void)setTempArray:(NSMutableArray *)value {
if(value!=tempArray){
[tempArray release];
tempArray = [value retain];
}
}
或者您可以使用@synthesized访问器方法自行保存编码。旁边的tempArray是一个实例变量的可怕名称。另请注意,每次创建新的tempArray时都会释放旧的tempArray - 最后一个实例何时清理?
这仍然不是很好,因为您的解析器类不应直接访问appDelegate中的实例变量。 Vardiables的tempArray和searchClass应该是私有的,但这不是重点,而是更多的设计问题。
url5在哪里发布?
这应该做什么?
if(!currentElementValue){
[currentElementValue release];
}
如果不存在,则释放currentElementValue吗?
[data2 release];
您是否保留了数据2?
- (void) dealloc {
[super dealloc];
[aSearchClass release];
[currentElementValue release];
//[self release];
}
我认为aSearchClass是appDelegate上的一个实例变量?
这可能听起来像是挑剔,但如果让你的代码清楚并且你确切地知道发生了什么,那么追踪泄漏就容易得多。
答案 1 :(得分:1)
您需要同时发布url5
和xmlParser5
,因为您已使用alloc
分配它们。
您还应该警惕在属性上调用release
,因为在@synthesize
实例变量时创建的标准setter通常会在设置新值之前释放变量的先前值。