对于给定的对象数组,如何同时 运行 多个 UIAnimation 块?

How do I run multiple UIAnimation blocks at the same time for a given array of objects?

我需要在屏幕上移动5个图像并做过渡效果,例如旋转->旋转动画完成时:移动(移动完成后:然后重复过程)

我可以得到 1 张图像来执行此操作,效果很好。

我遇到的问题是我需要对 5 张图像进行处理;要求是所有图像(或图像视图)都需要同时 运行 的动画。

我使用了一个自定义对象,里面有一个 UIImageView

-(void)stopRepeatingAnimationForView:(UIView *)view
{
    self.enableRepeatingAnimation = NO;
    [view.layer removeAllAnimations];
}

- (void)startRepeatingAnimationForView:(UIView *)view
{
    self.enableRepeatingAnimation = YES;
    [self repeatingAnimationForView:view];
}

- (void)repeatingAnimationForView:(UIView *)view
{
    //VICAirplane *planeObj = [self.airplanes objectAtIndex:0];
    for (VICAirplane *planeObj in self.airplanes) {


            [UIView animateWithDuration:3
                                  delay:1
                                options:UIViewAnimationOptionCurveLinear
                             animations:^{
                                 planeObj.imageView.transform = CGAffineTransformRotate(planeObj.imageView.transform, planeObj.angleToRotate);
                             } completion:^(BOOL finished) {

                                 if (finished==YES) {
                                     [UIView animateWithDuration:5
                                                           delay:0.0
                                                         options:UIViewAnimationOptionCurveLinear
                                                      animations:^{

                                                          planeObj.imageView.center = planeObj.rotateToLocation;

                                                      } completion:^(BOOL finished) {
                                                          if (finished==YES) {
                                                              if ( self.enableRepeatingAnimation )
                                                              {
                                                                  CGPoint rotateToLocation = [self generateRandomLocation];
                                                                  planeObj.rotateToLocation = rotateToLocation;

                                                                  [self performSelector:@selector(repeatingAnimationForView:) withObject:view afterDelay:0];
                                                              }
                                                          }
                                                      }];
                                 }
                             }];

    } // next


}

如果删除数组中的循环或简单地使其成为 1 个长度的数组,则动画效果很好。

但是如果我同时添加多个动画,它们就会开始失去完成状态,最终会变得一团糟。

我想做的是:

  1. 循环浏览我的 5 张图片
  2. 在每个图像上执行我的旋转 -> 移动 -> 重复(永远)动画

但我不确定如何让它适用于存储在数组中的多个 uiimageviews

有办法吗?

如果我正确理解你的问题,下面的代码应该可以满足你的要求。它旨在按以下顺序执行以下操作:

  1. 在相同的时间和相同的持续时间内,将 view/airplane/whatever 数组中的 所有 项旋转到新的旋转方向。
  2. 将 view/airplane/whatever 数组中的 所有 项同时并在相同的持续时间内翻译到它们的新位置。
  3. 在#2 的末尾,从#1 开始重复。

现在,对于我的代码,我创建了 VICAirplane 作为 UIView 的一个简单子类,它有一个 属性: @property (assign,nonatomic) CGPoint rotateToLocation.

基本上,您尝试使用一个 for 循环来迭代您的对象,但如果您在每个动画期间迭代数组,效果会更好。您绝对可以按照我在下面显示的方式链接它们,但您也可以为动画链的每个 "link" 创建单独的方法,然后每个方法遍历数组一次。在任何一种情况下,您都需要迭代数组 in/during 动画块,而不是在它之外。当您在它之外进行迭代时(如上面的代码所做的那样),您正在为每个对象创建一个单独的动画块,所有这些都将被独立处理。

无论如何,下面的代码创建了 5 个旋转的彩色方块,然后在连续的动画循环中以随机方式平移。

//  VICAirplane.h
#import <UIKit/UIKit.h>
@interface VICAirplane : UIView
@property (assign, nonatomic) CGPoint rotateToLocation;
@end
//  VICAirplane.m
#import "VICAirplane.h"
@implementation VICAirplane
@end

//  ViewController.h
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@end
//  ViewController.m
#import "ViewController.h"
#import "VICAirplane.h"
@interface ViewController () {

}
@property (strong, nonatomic) NSMutableArray *views;
@property (assign, nonatomic) BOOL enableRepeatingAnimation;
@end
@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    [self setupUserInterface];
}
- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    [self startRepeatingAnimation];
}
- (void)setupUserInterface {
    self.views = [NSMutableArray array];
    for (int i = 0; i < 5; i = i + 1) {
        VICAirplane *newView = [[VICAirplane alloc] initWithFrame:CGRectMake((i * 100) + 20, (i * 100) + 20, 80, 80)];
        switch (i % 4) {
            case 0:
                newView.backgroundColor = [UIColor blueColor];
                break;
            case 1:
                newView.backgroundColor = [UIColor redColor];
                break;
            case 2:
                newView.backgroundColor = [UIColor greenColor];
                break;
            case 3:
                newView.backgroundColor = [UIColor brownColor];
                break;
            case 4:
                newView.backgroundColor = [UIColor purpleColor];
                break;
            default:
                break;
        }
        [self.views addObject:newView];
        [self.view addSubview:newView];
    }
}
- (CGPoint)generateRandomLocation {
    CGFloat x = (CGFloat)arc4random_uniform(600);
    CGFloat y = (CGFloat)arc4random_uniform(600);
    return CGPointMake(x, y);
}
-(void)stopRepeatingAnimation {
    self.enableRepeatingAnimation = NO;
    [self.view.layer removeAllAnimations];
}
- (void)startRepeatingAnimation {
    self.enableRepeatingAnimation = YES;
    for (VICAirplane *subview in self.views) {
        subview.rotateToLocation = [self generateRandomLocation];
    }
    [self repeatingAnimation];
}
- (void)repeatingAnimation {
    [UIView animateWithDuration:3
                          delay:1
                        options:UIViewAnimationOptionCurveLinear
                     animations:^{
                         for (UIView *subview in self.views) {
                             // Just a random rotation between -2π and 2π
                             CGFloat rotationAngle = (arc4random_uniform(400 * M_PI) - (200 * M_PI)) / 100;
                             subview.transform = CGAffineTransformRotate(subview.transform, rotationAngle);
                         }
                     }
                     completion:^(BOOL finished) {
                         if (finished==YES) {
                             [UIView animateWithDuration:5
                                                   delay:0.0
                                                 options:UIViewAnimationOptionCurveLinear
                                              animations:^{
                                                  for (VICAirplane *subview in self.views) {
                                                      subview.center = subview.rotateToLocation;
                                                  }
                                              }
                                              completion:^(BOOL finished) {
                                                  if (finished==YES) {
                                                      if (self.enableRepeatingAnimation) {
                                                          for (VICAirplane *subview in self.views) {
                                                              subview.rotateToLocation = [self generateRandomLocation];
                                                          }
                                                          [self performSelector:@selector(repeatingAnimation) withObject:nil afterDelay:0.0f];
                                                      }
                                                  }
                                              }
                              ];
                         }
                     }
     ];
}
@end

我只是将我的循环放在应用程序的不同部分,现在它运行得更好了。

原来我是这样做的:

- (void)repeatingAnimationForView:(UIView *)view
{
    for (VICAirplane *planeObj in self.airplanes) {
    }
}

我不需要将 for 循环放入我的 startRepeatingAnimationForView 方法中,只需将参数传递给相同的方法

相反,我应该把它放在这里(我现在已经完成并且比原来的效果更好)

-(void)stopRepeatingAnimationForView:(UIView *)view
{
    self.enableRepeatingAnimation = NO;
    [view.layer removeAllAnimations];
}

- (void)startRepeatingAnimationForView:(UIView *)view
{
    self.enableRepeatingAnimation = YES;
    for (VICAirplane *planeObj in self.airplanes) {
        [self repeatAnimationWithParams:@{@"view":view, @"planeObj": planeObj}];
    }
}

-(void) repeatAnimationWithParams:(NSDictionary *)params
{
    VICAirplane *planeObj = params[@"planeObj"];

    [UIView animateWithDuration:2
                          delay:1
                        options:UIViewAnimationOptionCurveLinear
                     animations:^{
                         planeObj.imageView.transform = CGAffineTransformRotate(planeObj.imageView.transform, planeObj.angleToRotate);
                     } completion:^(BOOL finished) {

                         if (finished==YES) {
                             [UIView animateWithDuration:5
                                                   delay:0.0
                                                 options:UIViewAnimationOptionCurveLinear
                                              animations:^{

                                                  planeObj.imageView.center = planeObj.rotateToLocation;

                                              } completion:^(BOOL finished) {
                                                  if (finished==YES) {
                                                      if ( self.enableRepeatingAnimation )
                                                      {
                                                          CGPoint rotateToLocation = [self generateRandomLocation];
                                                          planeObj.rotateToLocation = rotateToLocation;

                                                          [self performSelector:@selector(repeatAnimationWithParams:)
                                                                     withObject:params
                                                                     afterDelay:0];
                                                      }
                                                  }
                                              }];
                         }
                     }];

}