【问题标题】:How to stop UIView Animation when needed?如何在需要时停止 UIView 动画?
【发布时间】:2014-09-15 12:20:48
【问题描述】:

我有这个代码:

-(void)animationLoop{
CGPoint oldPoint = CGPointMake(myCircleUIView.frame.origin.x, myCircleUIView.frame.origin.y);
[UIView animateWithDuration:1.0
                 animations: ^{ myCircleUIView.frame = CGRectMake(myCircleUIView.frame.origin.x + [self randomFloatingGenerator], myCircleUIView.frame.origin.y + [self randomFloatingGenerator], myCircleUIView.frame.size.width, myCircleUIView.frame.size.height); }
                 completion:
 ^(BOOL finished) {
     [UIView animateWithDuration:1.0
                      animations:^{ myCircleUIView.frame = CGRectMake(oldPoint.x, oldPoint.y, myCircleUIView.frame.size.width, myCircleUIView.frame.size.height);}
                      completion:
      ^(BOOL finished) {[self animationLoop];}];
 }];
}

但我试图在与动画交互时停止动画,但[myCircleUIView.layer removeAllAnimations]; 不会完成这项工作,有什么建议吗?

【问题讨论】:

  • 我相信2018年最好的办法就是使用UIViewPropertyAnimator。与此相比,旧的解决方案似乎是丑陋的黑客。

标签: ios animation uiview uiviewanimation


【解决方案1】:

当您使用CALayer's 停止动画时,-removeAllAnimations 将使用finished == NO 调用完成回调。所以像这样改变你的动画代码:

- (void)animationLoop {
    __weak id weakSelf = self;
    CGPoint oldPoint = CGPointMake(myCircleUIView.frame.origin.x, myCircleUIView.frame.origin.y);
    [UIView animateWithDuration:1.0
                     animations:^{
                         myCircleUIView.frame = CGRectMake(myCircleUIView.frame.origin.x + [weakSelf randomFloatingGenerator], myCircleUIView.frame.origin.y + [weakSelf randomFloatingGenerator], myCircleUIView.frame.size.width, myCircleUIView.frame.size.height);
                     }
                     completion:^(BOOL finished) {
                         if (!finished) return;
                         [UIView animateWithDuration:1.0
                                          animations:^{
                                              myCircleUIView.frame = CGRectMake(oldPoint.x, oldPoint.y, myCircleUIView.frame.size.width, myCircleUIView.frame.size.height);
                                          }
                                          completion:^(BOOL finished) {
                                              if (!finished) return;
                                              [weakSelf animationLoop];
                                          }];
                     }];
}

我还建议您不要将对 self 的强引用传递给复制到堆中的块,如果您真的不想这样做,因为可能有 retain cycle

【讨论】:

  • 在动画块中使用 self 是一个保留周期吗?我知道如果您将 self 与队列在同一类中被强引用的块结合使用,这是一个循环。但是,既然 UIView 的动画方法是类级别的方法,那么它们应该是没有引用循环的吧? (我问是因为它挑战了我的理解。不是因为我试图反驳你)。
  • 很好的问题,我也没有得到背后的原因,但认为每个人都这样做了所以我没有问:v
  • @Freddy,completion 块被复制到堆中以便稍后调用,因此增加了self 保留计数。如果不检查 finished 标志 self 将永远存在(因为递归)。然而,包括上面的修复解决了这个问题,但是self 保留计数会在更晚的时候减少(在动画完成并且块消失之后)。至于我,如果我真的不想保存self living,我不会将它作为对复制到堆中的块的强引用传递。只是为了确定 :) 我称之为a logical retain cycle
【解决方案2】:

在循环中添加 bool 并在需要停止动画时设置为 false,如下面的代码所示...

BOOL IsAnimationContinue=true;

-(void)animationLoop{
CGPoint oldPoint = CGPointMake(myCircleUIView.frame.origin.x, myCircleUIView.frame.origin.y);
[UIView animateWithDuration:1.0
             animations: ^{
                              if(IsAnimationContinue)
                              {
                               myCircleUIView.frame = CGRectMake(myCircleUIView.frame.origin.x + [self randomFloatingGenerator], myCircleUIView.frame.origin.y + [self randomFloatingGenerator], myCircleUIView.frame.size.width, myCircleUIView.frame.size.height); 
                              }}
             completion:^(BOOL finished) {
 [UIView animateWithDuration:1.0
                  animations:^{ 
                                 if(IsAnimationContinue)
                                {
                                 myCircleUIView.frame = CGRectMake(oldPoint.x, oldPoint.y, myCircleUIView.frame.size.width, myCircleUIView.frame.size.height);
                                }}
                  completion:
  ^(BOOL finished) {[self animationLoop];}];

}]; }

设置好了

IsAnimationContinue=False

停止动画

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-23
    • 1970-01-01
    • 1970-01-01
    • 2013-10-25
    • 2013-09-27
    • 2023-04-08
    相关资源
    最近更新 更多