Странная утечка памяти в Window: addSubView - PullRequest
1 голос
/ 10 марта 2012

прежде всего извините за мой английский :-) не очень хорошо.

У меня странная утечка памяти со следующим кодом (код после объяснения). У меня есть класс, FLWaitingView. Это простое представление с индикатором ожидания (плюс представление с фоном), используемое для того, чтобы сказать пользователю «дождаться загрузки данных». У него есть два простых метода: показать и отклонить. В методе show я нахожу главное окно приложения и добавляю подпредставления (вид ожидания и фоновый вид с различными анимациями). В методе dismiss я удаляю его из superview. В каждом шоу я проверяю, что представление еще не видно, используя статическую переменную bool (is_visible).

Странная вещь: в методе dismiss я использую:

[self.view removeFromSuperview];
[self.waitingView removeFromSuperview]; 

чтобы удалить два вида из окна, чтобы избежать их сохранения. Они правильно удалены, я могу проверить это с NSLog (для cicle на каждом подпредставлении окна). Но в INSTRUMENTS, используя функцию «mark heap», я вижу, что при каждой перезагрузке (новый экземпляр FLWaitingView, затем показ, затем удаление) старый экземпляр остается в памяти и продолжает увеличивать использование памяти. Очевидно, это не проблема вызывающего кода, потому что я правильно освобождаю объект:

//CALLING CODE
//customWaitingView is a property retained
self.customWaitingView = [[[FLWaitingView alloc]init]autorelease];
[self.customWaitingView show];

Более того, и я думаю, что это самая важная информация, если я переместу отображение вида в другой метод, вызываемый селектором, утечка исчезнет !!!

Теперь я показываю «неправильный» код и, после, «исправление». Я хотел бы понять, почему это происходит.

- (void)show
{

    if (!is_visible){

        id appDelegate = [[UIApplication sharedApplication] delegate];
        UIWindow *window = [appDelegate window];
        self.waitingLabel.text = @"Attendere";

        self.view.alpha = 1.0;
        self.waitingView.alpha = 1.0;

        [window addSubview:self.view];
        [window addSubview:self.waitingView];
        [self.waitingIndicator startAnimating];
        self.view.frame = window.frame;
        self.waitingView.center = window.center;
        // "Pop in" animation for alert
        [self doPopInAnimationWithDelegate:self];
        // "Fade in" animation for background
        [self doFadeInAnimation];
        is_visible = YES;
    } else {
        NSLog(@"FLWaitingView %@ already visible, do nothing", self);
    }

}


- (void)dismiss
{
    [UIView beginAnimations:nil context:nil];
    self.view.alpha = 0.0;
    self.waitingView.alpha = 0.0;
    [UIView commitAnimations];
    [self.waitingIndicator stopAnimating];

    //here is the problem
    [self.view removeFromSuperview];
    [self.waitingView removeFromSuperview]; 
    is_visible = NO;
}

приведенный выше код является "неправильным", но если я добавлю

[self performSelector:@selector(alertDidFadeOut) withObject:nil afterDelay:0.5];

в методе dismiss и новом методе (очевидно, удаляющий избыточный код из метода dismiss):

- (void)alertDidFadeOut
{      
    //here the memory is correctly released
    [self.view removeFromSuperview];
    [self.waitingView removeFromSuperview];
    is_visible = NO;
}

память освобождена правильно. Зачем?????? Заранее спасибо

Fabio

1 Ответ

0 голосов
/ 10 марта 2012

Ваше представление не будет выпущено так, как вы ожидаете, потому что в тот момент, когда вы его выпускаете, с ним все еще связаны анимации.Вы можете правильно отпустить его только после завершения анимации.

Ваш второй метод работает, потому что анимация длится менее 0,5 секунды - освобождающий код вызывается после того, как представление освобождается от всех анимаций.

Правильный способ анимировать представление - создатьанимация и назначение ее делегата или, возможно, более элегантное решение - использовать блочную анимацию, например:

- (void)dismiss
{

    [[UIApplication sharedApplication] beginIgnoringInteractionEvents];                             

    [UIView animateWithDuration: 0.15
        animations: ^{
            self.view.alpha = 0.0;
            self.waitingView.alpha = 0.0;
                     }
        completion: ^(BOOL finished){
            [self.waitingIndicator stopAnimating];
            [self.view removeFromSuperview];
            [self.waitingView removeFromSuperview]; 
            is_visible = NO;    
            [[UIApplication sharedApplication] endIgnoringInteractionEvents];                             
        }];   
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...