Сбой памяти в UIPopoverController - PullRequest
4 голосов
/ 30 июня 2011

Я сейчас потратил несколько дней, чтобы понять, что происходит, и ради своей жизни я не вижу, что я делаю неправильно.Я выскакиваю 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];

Заранее спасибо за любую помощь !!!Любые идеи приветствуются !!

-Кевин

Ответы [ 3 ]

4 голосов
/ 30 июня 2011

[myPop dismissPopoverAnimated:YES] продолжит обращаться к вашему объекту даже после вызова метода, потому что вы установили YES для анимации (для выполнения анимации для этого требуется таймер и другие вещи)

Таким образом, вместо немедленного освобождения объекта, вы можете пометить его как авто-релиз, чтобы отложить это действие, которое фактически может решить его или нет.

Или отложите выпуск на время, после которого вы убедитесь, что анимация будет завершена. Для этого вы можете использовать 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 класса.

3 голосов
/ 30 июня 2011

Добавьте следующие ключи в Вашу информацию Exectables-> вкладка Arguments-> переменные окружения

NSZombieEnabled = YES

CFZombie = 5

MallocStackLoggingNoCompact = 1

тогда, когда вы получите автоматический сбой, вы получите сообщение, похожее на это

(gdb) continue

2011-06-09 11: 46: 08.404 test [6842: 40b] * - [_ NSArrayI release]: сообщение отправлено на освобожденный экземпляр 0X64a4900

затем введите

(gdb) info malloc-history 0x64a4900

это даст вам полную историю.

Может быть, это поможет вам найти место.

также вы можете использовать команду where при сбое.

0 голосов
/ 08 сентября 2011

Самый быстрый способ избежать ожидания завершения анимации - установить popoverController.delegate = nil, как только вы закрываете всплывающее окно или вызывается метод Popover Delegate.

...