UIAlertController内存泄漏

时间:2015-10-14 03:19:40

标签: ios objective-c memory-leaks instruments

我没有使用ARC。

通过仪器测试泄漏在呈现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":@""}];
}

最后,showPopupMessage BaseController的父级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]; }

D:\Users\saturdayplace\Documents\www\accntr>node -v
v4.1.2

D:\Users\saturdayplace\Documents\www\accntr>which node
C:\Program Files\nodejs\node.EXE

D:\Users\saturdayplace\Documents\www\accntr>echo %path%
< a bunch of stuff that includes C:\Program Files\nodejs\ >

为什么仪器显示泄漏? 我看了看这些主题:

iOS 8 Only Memory Leak with UIAlertController or UIActionSheet

UIAlertController memory leak/issues - Swift

他们似乎暗示这可能是一个错误...或者它可能是我错过的保留周期。

1 个答案:

答案 0 :(得分: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