2015-07-03 69 views
2

我构建了一个简单的应用程序,它从HockeyApp获取报告。但是,当我使用内存泄漏工具运行应用程序时,它显示执行getReport操作时发生内存泄漏。我无法理解仪器中显示的所有信息。如何修复Objective-C中的内存泄漏?

这里是这会导致内存泄漏按钮动作方法:

- (IBAction)getReports:(id)sender { 

//initialize url that is going to be fetched. 
NSURL *url = [NSURL URLWithString:@"https://rink.hockeyapp.net/api/2/apps/APP_ID/crash_reasons"]; 

//initialize a request from url 
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; 
[request addValue:tokenReceived forHTTPHeaderField:@"X-HockeyAppToken"]; 

[request setHTTPMethod:@"GET"]; 
[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"]; 

//initialize a connection from request 
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self]; 
self.getReportConnection = connection; 

} 


- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData*)data{ 

    if (connection==getReportConnection) { 

    [self.receivedData appendData:data]; 

    NSLog(@"data is %@",data); 

    NSString *responseString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 

    NSError *e = nil; 
    NSData *jsonData = [responseString dataUsingEncoding:NSUTF8StringEncoding]; 

    NSDictionary *JSON = [NSJSONSerialization JSONObjectWithData:jsonData options: NSJSONReadingMutableContainers error: &e]; 
    NSLog(@"login json is %@",JSON); 
    NSLog(@"reason json is %@",JSON[@"reason"]); 

    [JSON[@"crash_reasons"] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { 


     [reportArray addObject:obj[@"reason"]]; 
     NSLog(@"index = %lu, Object For title Key = %@", (unsigned long)idx, obj[@"reason"]); 
    }]; 

    NSError *error = nil; 
    NSArray *jsonArray = [NSJSONSerialization JSONObjectWithData:jsonData 
                 options:kNilOptions error:&error]; 

    if (error != nil) { 
     NSLog(@"Error parsing JSON."); 
    } 
    else { 
     NSLog(@"Array: %@,array count is %d", jsonArray,jsonArray.count); 
    } 

    // [reportArray addObject:[jsonArray objectAtIndex:0]]; 

    if (JSON!=NULL) { 
     UIAlertView *alert=[[UIAlertView alloc]initWithTitle:@"Reports succesfully retrieved" message:@"" delegate:self cancelButtonTitle:@"Ok" otherButtonTitles: nil]; 
     [alert show]; 
    } 

     } 
} 

// This method receives the error report in case of connection is not made to server. 
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{ 

UIAlertView *errorAlert=[[UIAlertView alloc]initWithTitle:@"Wrong Login" message:nil delegate:self cancelButtonTitle:@"ok" otherButtonTitles: nil]; 
[errorAlert show]; 
NSLog(@"error is %@",error); 
} 

// This method is used to process the data after connection has made successfully. 
- (void)connectionDidFinishLoading:(NSURLConnection *)connection{ 

} 

我看到之前的警报视图显示在didRecieveData方法发生内存泄漏。

这里是表示内存泄漏内存泄漏仪器的屏幕截图:

enter image description here

我无法理解其部分代码导致内存泄漏。任何人都可以告诉我如何识别导致泄漏仪器泄漏内存的代码部分?

编辑:当运行在模拟器上的应用程序,该仪器没有显示任何内存泄漏:

这里是截图: enter image description here

再次当我在设备运行应用程序,该仪器向我展示了内存泄漏: enter image description here

我看着泄漏部分,我发现NSmutableArray是造成泄漏: enter image description here enter image description here

我在我的代码中只使用了一个NSMutableArray。我宣布它在.h文件:

@property (nonatomic,strong) NSMutableArray *reportArray; 

viewDidLoad分配它:

reportArray=[[NSMutableArray alloc]init]; 

didRecieveData装好了:

[reportArray addObject:obj[@"reason"]]; 

堆栈跟踪快照:

enter image description here enter image description here enter image description here

+0

请注意,右侧“快照”之上的一个工具按钮选择一个堆栈跟踪,可以显示泄漏对象的分配情况。 –

+0

添加了堆栈跟踪快照! –

回答

1

试试这个:

reportArray = [[[NSMutableArray alloc] init] autorelease]; 

connectionDidFinishLoading:connection:didFailWithError:方法来设置

reportArray = nil 

终于在项目>构建阶段>编译源代码添加-fno-objc-arc为编译器标志这个档案(编辑,抱歉)。然后点击产品菜单>再次分析(command + shift + B)并检查内存泄漏是否仍然存在。

+0

P.S.还要在'connection:didReceiveResponse:'方法中分配并初始化'reportArray'。 – Lucifer

+0

我正在使用ARC。我想我不能提autorelease。 –

+0

我明白了。如果将'-fno-objc-arc'标志添加到** Build Phases> Compile Sources **文件列表中的特定文件中,则该文件的ARC将被禁用。 – Lucifer

0

这可能是苹果的泄漏 - 确定看起来像来自UIAlertView/UIAlertConnection。您可以尝试使用UIAlertConnection实现警报,并查看它是否消失 - Apple可能没有尽可能多地测试后向兼容的UIAlertView实现。

它不会出现在泄漏,但请注意,NSURLConnection保留其委托,并在你的情况下,你有你的委托保留它看起来像NSURLConnection。如果我没有弄错,那应该是一个保留循环。当连接完成或发生故障时,请确保将其分开(清除委托,或清除控制器上的连接)。