Рекурсивный метод, содержащий блок UIAnimation, как правильно выпустить - PullRequest
2 голосов
/ 12 июля 2011

Я сделал небольшой «загрузчик», который я могу прикрепить к интерфейсу, когда мне это нужно.Очень похоже на UISpinnerView.

Он имеет некоторую логику (я упростил код в блоке для этого поста), которая требует его рекурсивного вызова.Я делаю это так:

- (void) blink {

    tick++;

    if (tick > kNumberOfLights)
        tick = 0;

    UIView *lightOne = [self viewWithTag:kLightStartIndex];
    UIView *lightTwo = [self viewWithTag:kLightStartIndex+1];   

    [UIView animateWithDuration:0.5
                          delay: 0.0
                        options: UIViewAnimationOptionAllowUserInteraction | UIViewAnimationOptionCurveEaseOut
                     animations:^{

                         if (tick == 0) {

                             [lightOne setAlpha:kLightOn];
                             [lightTwo setAlpha:kLightOff];                            

                         } else if (tick == 1) {

                             [lightOne setAlpha:kLightOff];
                             [lightTwo setAlpha:kLightOn];    
                         }
                     }
                     completion:^(BOOL finished){
                             [self blink];    
                     }];

}

Метод [self blink] вызывается, когда представление добавляется в супер-представление.

В классе Loader не сохраняется никаких объектов, поэтому, когдаЯ удаляю это в супер представлении, это выпущено.Проблема состоит в том, что если блок анимации работает, когда я освобождаю представление, блок завершения вызовет освобожденный объект и вызовет ошибку:

(20380,0xa0a29540) malloc: * mmap(размер = 2097152) не удалось (код ошибки = 12) * ошибка: невозможно выделить регион

В консоли и ошибка:

__ [LoaderClass мигает] _block_invoke_2

в отладочном навигаторе.

Как убедиться, что правильно разобрали представление, когда оно удалено из суперпредставления?

1 Ответ

1 голос
/ 06 сентября 2011

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

Переменные экземпляра:

BOOL isBlinking;
BOOL releaseWhenDoneAnimating;

Initialize isBlinking = NO и releaseWhenDoneAnimating = NO.

- (void)release
{
    if(!isBlinking) {
        [super release];
        return;
    }

    releaseWhenDoneAnimating = YES;
}

- (void) blink {

    isBlinking = YES;

    if(releaseWhenDoneAnimating) {
        [super release];
        return;
    }

    tick++;

    if (tick > kNumberOfLights)
        tick = 0;

    UIView *lightOne = [self viewWithTag:kLightStartIndex];
    UIView *lightTwo = [self viewWithTag:kLightStartIndex+1];   

    [UIView animateWithDuration:0.5
                      delay: 0.0
                    options: UIViewAnimationOptionAllowUserInteraction | UIViewAnimationOptionCurveEaseOut
                 animations:^{

                     if (tick == 0) {

                         [lightOne setAlpha:kLightOn];
                         [lightTwo setAlpha:kLightOff];                            

                     } else if (tick == 1) {

                         [lightOne setAlpha:kLightOff];
                         [lightTwo setAlpha:kLightOn];    
                     }
                 }
                 completion:^(BOOL finished){
                     [self blink];    
                 }];

}
...