2015-10-14 36 views
2

我沒有使用ARC。UIAlertController內存泄漏

測試通過儀器泄漏給我提出一個UIAlertController時,以下幾點:

enter image description here

這似乎是在抱怨這個代碼塊時,我檢查調用樹。不知道有多少,這是相關但無論如何...

-(void) connection:(NSURLConnection*)connection didFailWithError:(NSError*)error { 
    // bunch of code 

    #ifndef NDEBUG 
    NSString* err_msg = [NSString stringWithFormat:@"%@%ld", @"Error number ", (long) error_code]; 
    // @property (nonatomic, retain) id <DownloadMonitor> m_downloadMonitor; 
    [_m_downloadMonitor showDownloadAlert:err_msg withTitle:@"Download error"]; 
    #endif 

m_downloadMonitor實際上是一個類型DashboardController的對象,定義如下:

@interface DashboardController : BaseController <UIAlertViewDelegate, UITableViewDelegate, UITableViewDataSource, DownloadMonitor> 

DownloadMonitor是定義自定義協議如下:

@protocol DownloadMonitor <NSObject> 
-(void) downloadFinishedFor:(UIProgressView*)progress_bar; 
-(void) downloadFailedFor:(UIProgressView*)progress_bar; 
-(void) showDownloadAlert:(NSString*)message withTitle:(NSString*)title; 
@end 

方法showDownloadAlertDashboardController定義如下:

-(void) showDownloadAlert:(NSString*)message withTitle:(NSString*)title { 
    [self showPopupMessage:message withTitle:title andDelegate:self andActionHandlers:@{@"OK":@""}]; 
} 

最後,showPopupMessageBaseController(父類的DashboardController):

- (void)showPopupMessage: (NSString*)message withTitle:(NSString*)title andDelegate:(BaseController*)delegate andActionHandlers:(NSDictionary*)handlers { 
    UIAlertController* alert = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert]; 

    for (id key in handlers) { 
    NSString* button_name = (NSString*) key; 
    NSString* handler_name = (NSString*) [handlers objectForKey:key]; 
    UIAlertAction* action; 

    if (! [handler_name isEqualToString:@""]) { 
     SEL sel = NSSelectorFromString(handler_name); 
     action = [UIAlertAction actionWithTitle:button_name style:UIAlertActionStyleDefault handler:^(UIAlertAction * action)   { 
      [delegate performSelector:sel]; 
      [alert dismissViewControllerAnimated:YES completion:NULL]; 
     }]; 
    } 
    else { 
     action = [UIAlertAction actionWithTitle:button_name style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { 
     [alert dismissViewControllerAnimated:YES completion:NULL]; 
     }]; 
    } 

    [alert addAction:action]; 
    } 

    [delegate presentViewController:alert animated:YES completion:nil]; 
} 

爲什麼儀器顯示的泄漏? 我看了一下這些線程:

iOS 8 Only Memory Leak with UIAlertController or UIActionSheet

UIAlertController memory leak/issues - Swift

他們似乎表明它可能是一個錯誤......或者它可能是一個保留,我已經錯過週期。

回答

0

我認爲你有一個保留循環:

showPopupMessage方法,行動加入到alert它保留它們。您可以定義引用alert的塊(因爲它使用它)。這些街區正在保留alert

所以,alert保留塊保留``警報:你的保留圈!

你應該嘗試:

__block __typeof__(alert) blockAlert = alert; 

action = [UIAlertAction actionWithTitle:button_name style:UIAlertActionStyleDefault handler:^(UIAlertAction * action)   { 
    [delegate performSelector:sel]; 
    [blockAlert dismissViewControllerAnimated:YES completion:NULL]; 
}]; 

__block存儲類型修飾符將參考警報不保留它(在非ARC模式):https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Blocks/Articles/bxVariables.html#//apple_ref/doc/uid/TP40007502-CH6-SW6

+0

謝謝!這似乎已經阻止它報告相同的泄漏,但現在它compains關於此行:'UIAlertController * alert = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert];' – Ash

+0

另外,我猜你的代碼應該是在這一行中替換'alert' [alert dismissViewControllerAnimated:YES completion:NULL];'? – Ash

+0

是的,你是對的:我用'alert'切換了'delegate'(這是我的第一個可疑變量)。 '代理'必須保持原樣,但àlert'必須用弱'__block'ref'blockAlert'代替。如果我的回答是正確的,請不要忘記將其標記爲正確/被接受的答案。 –