关闭popover,然后popToRootViewController,EXC_BAD_ACCESS

问题描述:

我碰到了,当我popToRootViewController,这是我设置它的方式。关闭popover,然后popToRootViewController,EXC_BAD_ACCESS

我:

@property (nonatomic, retain) UIPopoverController *popover; 

中的dealloc:

[popover release]; 

当按钮被按下

if (self.popover == nil) { 
    DetailViewController *detailView = [[[DetailViewController alloc] init] autorelease]; 
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(GoToTest:) name:TestDetailPressed object:detailView]; 
    self.popover = [[[UIPopoverController alloc] initWithContentViewController:detailView] autorelease]; 
    self.popover.delegate = self; 
    [self.popover presentPopoverFromRect:frame inView:self.scrollView permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES]; 
} 

DetailViewController本质上只是一个UITableView。当选择一排,我发布一个通知回到这个当前类GoToTest:

- (void)GoToTest:(NSNotification *)notification { 
    if ([self.popover isPopoverVisible]) { 
     [self.popover dismisspopoverAnimated:YES]; 
     [self handleDismissedPopover:self.popover]; 
    } 
    [self.navigationController popToRootViewControllerAnimated:NO]; 
} 

- (void)handleDismissedPopover:(UIPopoverController *)popoverController { 
    self.popover = nil; 
    self.popover.delegate = nil; 
    [[NSNotificationCenter defaultCenter] removeObserver:self name:TestDetailPressed object:nil]; 
} 

- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController { 
    [self handleDismissedPopover:popoverController; 
} 

当我在仪器运行它,我得到的僵尸消息

-[UIPopoverController _popoverDismissAnimationCompleted] 

UIViewController有此时的refCt为-1。

你可能想改变self.popover = nillpopover = nil因为第一(self.popover = nil)将调用属性setter,释放旧值并设置成员为零。另外,将属性nil前的代表置零。

要修复,改变这种:

- (void)handleDismissedPopover:(UIPopoverController *)popoverController { 
    self.popover = nil; 
    self.popover.delegate = nil; 
    [[NSNotificationCenter defaultCenter] removeObserver:self name:TestDetailPressed object:nil]; 
} 

要:

- (void)handleDismissedPopover:(UIPopoverController *)popoverController { 
    popover.delegate = nil; 
    popover = nil; 
    [[NSNotificationCenter defaultCenter] removeObserver:self name:TestDetailPressed object:nil]; 
} 

如果还是不行,在调试器设置NSZombieEnabledMallocStackLoggingguard malloc。然后,当你的应用程序崩溃,在gdb的控制台输入:

(gdb) info malloc-history 0x543216 

替换0x543216与导致崩溃的对象的地址,你会得到一个更加有用的堆栈跟踪,它应该帮助你查明导致问题的代码中的确切行。

See this article for more detailed instructions.

+0

我会想象popover.delegate = nil; popover后=零;是毫无意义的。 – jbat100

+0

@ jbat100它是,很好的捕获。更新回答) – chown

+0

@chown malloc:使用标准记录器记录malloc堆栈到磁盘是什么意思? –

而且,你显式调用:在dealloc中

[popever release]; 

?因为你这样做:

self.popover = nil; 

,将释放对象,你不必担心它在你的dealloc。但是,就像@chown说的那样,使用Instruments Zombie工具,它会马上告诉你发生了什么。