2015-07-03 34 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。如果我沒有弄錯,那應該是一個保留循環。當連接完成或發生故障時,請確保將其分開(清除委託,或清除控制器上的連接)。