开发者

Memory Crash in UIPopoverController

I've now invested days in trying to figure out what is going on and for the life of me I can't see what I am doing wrong. I am popping up a UIPopover when the user touches a point on the screen. The popover has a tab controller and table view that displays information about that point. But when the popover is dismissed, it crashes claiming that: -[UIAnimator removeAnimationsForTarget:]: message sent to deallocated instance

Here is the code that loads the view controller:

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;
}

The actual MyViewController is just a UIViewController that with (abridged for brevity) 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 is nothing more than [super dealloc] since everything is essentially owned by the view and the view controller will take care of it. When the myPop is released, in DidDismissPopover, the view is also released, so that seems to work okay. But very soon thereafter, I get 开发者_JS百科the crash.

Do I need to do something special to discard the tab view or table view when the popup dismisses?

I am using an autorelease on the cells in the table, should I stop doing that?

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

Thank you in advance for any help!!! Any ideas at all are greatly appreciated!!

-Kevin


[myPop dismissPopoverAnimated:YES] will continue to access you object even after the method call because you set YES for the animation (there is a timer and other stuff going under the hood to perform the animation for that)

So, instead of immediately releasing the object, you could mark it as autorelease to postpone this action, which actually might solved it or not.

Or postpone the release to a time after that makes tyou sure thta the animation will be finished. You could use GCD for that (if you are using iOS 4+) and as the default time for animation in UIKit is 0.3s, the code bellow should do the trick.

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];
});

EDIT: You should use this time only for the test propose as it is far from being the right way to release an object.

You should store a pointer to your UIPopover and release it in your class dealloc method.


Add following keys in yor Exectables info->Arguments tab-> enviroment variables

NSZombieEnabled = YES

CFZombie = 5

MallocStackLoggingNoCompact = 1

then when you get crash automatically you get a message some thing like this

(gdb) continue

2011-06-09 11:46:08.404 test [6842:40b] * -[_NSArrayI release]:message sent to deallocated instance 0X64a4900

then type

(gdb) info malloc-history 0x64a4900

it will give you complete history.

May be it helps you to find the place.

also you can use where command when you got crash.


The fastest way to avoid waiting for animation to end is to set popoverController.delegate = nil as soon as you dismiss the popup or the Popover Delegate method

- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController

is called.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜