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

发布于 2024-11-19 09:24:26 字数 1520 浏览 5 评论 0原文

我做了一个小的“加载器”,当我需要它时我可以将其粘贴在用户界面上。很像 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眨眼]

Loader类中没有保留任何对象,所以当我在超级视图中删除它时 它被释放了。问题是,如果当我释放视图时动画块正在运行,则完成块将调用已释放的对象并导致错误:

(20380,0xa0a29540) malloc: * mmap(size=2097152) 失败(错误 代码=12) *错误:无法分配区域

在控制台中,错误:

__[LoaderClass眨眼]_block_invoke_2

调试导航器中的

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

I did a small "loader" that I can stick on the UI when I need it. Much like the UISpinnerView.

It has some logic (I simplified the code in the block for this post) that require it to be recursively called. I do it like this:

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

}

The method [self blink] is called when the view is added to a super view.

There are no objects retained in the Loader class, so when I remove it in the super view
it is released. The problem is that if the animation block is running when I release the view, the completion block will call a deallocated object and cause the error:

(20380,0xa0a29540) malloc: * mmap(size=2097152) failed (error
code=12)
*
error: can't allocate region

In the console and the error:

__[LoaderClass blink]_block_invoke_2

in the Debug Navigator.

How do I make sure to correctly tear down the view when it is removed from the super view?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

度的依靠╰つ 2024-11-26 09:24:26

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

实例变量:

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

}

Overriding release is usually a bad idea, but this case might be an exception to the rule.

Instance variables:

BOOL isBlinking;
BOOL releaseWhenDoneAnimating;

Initialize isBlinking = NO and 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];    
                 }];

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文