UIPopoverController中的内存崩溃

时间:2011-06-30 10:56:34

标签: objective-c ios ipad memory-management uipopover

我现在已经花了好几天时间试图弄清楚发生了什么,为了我的生活,我看不出我做错了什么。当用户触摸屏幕上的某个点时,我弹出一个UIPopover。弹出框有一个选项卡控制器和表视图,显示有关该点的信息。但当弹出被解雇时,它崩溃声称: - [UIAnimator removeAnimationsForTarget:]:发送到解除分配的实例的消息

以下是加载视图控制器的代码:

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,为了简洁起见,简称为init:

  - (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只不过是[super dealloc],因为一切都基本上由视图拥有,视图控制器会处理它。当myPop发布时,在DidDismissPopover中,视图也会被释放,所以看起来似乎没问题。但很快,我就崩溃了。

当弹出窗口解散时,是否需要做一些特殊的事情来丢弃标签视图或表格视图?

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

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

提前感谢您的帮助!!!任何想法都非常感谢!!

-Kevin

3 个答案:

答案 0 :(得分:4)

即使在方法调用之后,

[myPop dismissPopoverAnimated:YES]仍将继续访问您的对象,因为您为动画设置了YES(有一个计时器和其他内容可以执行动画)< / p>

因此,不是立即释放对象,而是将其标记为自动释放以推迟此操作,这实际上可能会解决它。

或者将发布推迟到一段时间之后,确保动画完成。您可以使用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方法中。

答案 1 :(得分:3)

在yor Exectables info-&gt; Arguments tab-&gt;中添加以下键:环境变量

NSZombieEnabled = YES

CFZombie = 5

MallocStackLoggingNoCompact = 1

然后当您自动崩溃时,您会收到一条消息 像这样的事情

  

(gdb)继续

     

2011-06-09 11:46:08.404测试[6842:40b] * - [_ NSArrayI   发布]:消息发送到解除分配的实例0X64a4900

     

然后输入

     

(gdb)info malloc-history 0x64a4900

它将为您提供完整的历史记录。

可能会帮助您找到这个地方。

你也可以在崩溃时使用where命令。

答案 2 :(得分:0)

避免等待动画结束的最快方法是在解除弹出窗口或Popover Delegate方法时立即设置popoverController.delegate = nil

- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController

被召唤。