4

我现在已经花了几天时间试图弄清楚发生了什么,对于我的生活,我看不出我做错了什么。当用户触摸屏幕上的一个点时,我会弹出一个 UIPopover。弹出框有一个选项卡控制器和表格视图,用于显示有关该点的信息。但是当弹出窗口被解除时,它会崩溃并声称:-[UIAnimator removeAnimationsForTarget:]: message sent to deallocated instance

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

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 只是一个带有(为简洁起见)init 的 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 只不过是 [super dealloc],因为一切本质上都归视图所有,视图控制器会处理它。当 myPop 被释放时,在 DidDismissPopover 中,视图也被释放,所以这似乎工作正常。但不久之后,我遇到了崩溃。

当弹出窗口消失时,我是否需要做一些特别的事情来丢弃选项卡视图或表格视图?

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

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

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

-凯文

4

3 回答 3

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方法中。

于 2011-06-30T11:10:46.237 回答
3

在您的 Exectables 信息-> 参数选项卡-> 环境变量中添加以下键

NSZombieEnabled = YES

CFZombie = 5

MallocStackLoggingNoCompact = 1

然后当您自动崩溃时,您会收到类似这样的消息

(gdb) 继续

2011-06-09 11:46:08.404 测试 [6842:40b] * -[_NSArrayI 发布]:发送到已释放实例 0X64a4900 的消息

然后输入

(gdb) 信息 malloc 历史 0x64a4900

它会给你完整的历史。

也许它可以帮助你找到那个地方。

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

于 2011-06-30T11:07:24.260 回答
0

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

- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController

叫做。

于 2011-09-08T17:11:00.170 回答