2011-06-30 32 views
4

我已经投入了数天的时间来试图弄清楚发生了什么事情,并且对于我的生活我看不到我做错了什么。当用户触摸屏幕上的一个点时,我弹出一个UIPopover。弹出窗口有一个选项卡控制器和表格视图,显示关于该点的信息。但是,当酥料饼被驳回,它崩溃声称: - [UIAnimator removeAnimationsForTarget:]:消息发送到释放实例UIPopoverController中的内存崩溃

这里被加载视图控制器代码:

MyViewController *popView = [[MyViewController alloc] init]; 
myPop = [[UIPopoverController alloc] initWithContentViewController:pop]; 
[popView release]; 
myPop.delegate = self; 
[airportPop setPopoverContentSize:popView.view.frame.size]; 
[airportPop presentPopoverFromRect:CGRectMake(location.x,location.y,1,1) inView:self.mainView permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES]; 

- (void)dismissPopover { 
    if(myPop != nil) { 
     [myPop dismissPopoverAnimated:YES]; 
     [myPop.delegate popoverControllerDidDismissPopover:airportPop]; 
    } 
} 

- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController { 
    [myPop release]; 
    myPop = nil; 
} 

实际MyViewController是只是一个UIViewController与(删节为了简洁)初始化:

- (id)init 
{ 
    self = [super init]; 
    //create a newview 
    self.view = popView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, POPUP_WIDTH, POPUP_HEIGHT)]; 
    [popView release]; 

    topBar = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, POPUP_WIDTH, 30)]; 
      .... 
    [popView addSubview:topBar]; 
    [topBar release]; 

    //create a table view 
    self.table = [[UITableView alloc] initWithFrame:CGRectMake(0, 30, POPUP_WIDTH, POPUP_HEIGHT-30-49)]; 
     table.delegate = table.dataSource = self; 
     .... 

    //create a tab bar 
    tabBar = [[UITabBar alloc] initWithFrame:CGRectMake(0, POPUP_HEIGHT-49, POPUP_WIDTH, 49)]; 
    tabBar.delegate = self; 

    [popView addSubview:tabBar]; 
    [popView addSubview:table]; 

    [tabBar release]; 
    [table release]; 
    return(self); 
} 

dealloc的无非是[超级的dealloc]因为一切基本上是由视图拥有和视图控制器会照顾Ø多f it。当myPop发布时,在DidDismissPopover中,视图也被释放,所以这似乎工作正常。但不久之后,我发生了这起事故。

当弹出窗口关闭时,我是否需要做一些特殊的操作来放弃标签视图或表格视图?

我在表中的单元格上使用autorelease,我应该停止这样做吗?

 cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease]; 

预先感谢您的帮助!任何想法都非常感谢!

-Kevin

+0

什么是'popView'? –

回答

4

[myPop dismissPopoverAnimated:YES]将继续访问你的对象,不管方法调用之后,因为你的动画设定YES(有一个计时器和其他的东西去引擎盖下执行该动画)

所以,与其立即释放该对象,您可以将其标记为autorelease以推迟此操作,这实际上可能会解决该问题。

或者推迟释放到一定时间后,确保动画完成。你可以使用GCD(如果你使用的是iOS 4+),并且作为UIKit中动画的默认时间是0.3秒,下面的代码应该可以做到。

double delayInSeconds = 0.3; 
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC); 
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ 
    [myPop.delegate popoverControllerDidDismissPopover:airportPop]; 
}); 

编辑:你应该使用这个时间只为测试建议,因为它是远远没有正确的方式来释放一个对象。

您应该存储一个指向UIPopover的指针,并将其释放到您的类dealloc方法中。

+0

是的 - 这就是它......设置Animated为NO似乎完全解决了崩溃问题。 (使用autorelease没有。)所以,这是有道理的,但是如何知道什么时候释放popover? –

+0

顺便说一句,0.3秒没有工作..我继续前进,并将其设置为5,并没有坠毁,因为。 –

3
按照侑Exectables信息 - >参数键标签 - >环境变量

NSZombieEnabled = YES 

CFZombie = 5 

MallocStackLoggingNoCompact = 1 

然后当你崩溃,你会自动获得一个消息 这样

一些事情

添加

(gdb)continue

2011-06-09 11:46:08.404测试[6842:4 0B] * - [_ NSArrayI 发布]:发送到释放实例0X64a4900

然后键入

(GDB)信息的malloc历史0x64a4900

它会给你一个完整的历史信息。

可能是它可以帮助你找到的地方。

还可以在碰撞时使用where命令。

+0

这就是我知道它在UIAnimator中的原因。每次调用的“发布的类”都会有所不同,但通常会在崩溃时尝试访问表或Tab视图。 –

+0

顺便说一下,不知道CFZombie - 也会试试这个... –

+0

有没有一种方法可以在lldb中使用这个调试工具? – atreat

0

避免等待动画结束,最快的方式就是尽快建立popoverController.delegate = nil为您关闭弹出窗口或酥料饼的委托方法

- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController 

被调用。

+1

这不适用于编程式关闭popovers。从苹果方面来说,这是非常愚蠢的,不提供一个完整的回调或呼叫“didDismissPopover”呼叫。 – BastiBen