包含UIAnimation块的递归方法,如何正确释放

时间:2011-07-12 11:40:54

标签: cocoa-touch memory-management core-animation objective-c-blocks uianimation

我做了一个小型的“加载器”,我可以在需要时粘贴在UI上。很像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(size = 2097152)失败(错误   代码= 12)   * 错误:无法分配区域

在控制台和错误中:

  

__ [LoaderClass blink] _block_invoke_2

在Debug Navigator中。

如何从超级视图中删除视图时,如何确保正确拆除视图?

1 个答案:

答案 0 :(得分:1)

覆盖释放通常是一个坏主意,但这种情况可能是规则的例外。

实例变量:

BOOL isBlinking;
BOOL releaseWhenDoneAnimating;

初始化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];    
                 }];

}