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

Мне нужно переместить 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. Выполнить мой поворот -> переместить -> повторить (навсегда) анимацию на каждом изображении

Но я не уверен, как заставить это работать для нескольких представлений uiimage, сохраненных в массиве

Есть ли способ сделать это?

2 ответа

Решение

Если я правильно понимаю ваш вопрос, следующий код должен делать то, что вы хотите. Он предназначен для выполнения следующих действий в указанном порядке:

  1. Поверните все элементы в виде / самолете / любом массиве в их новые вращения одновременно и в течение той же продолжительности.
  2. Переведите все элементы вида / самолета / любого массива в их новые местоположения одновременно и в течение той же продолжительности.
  3. В конце № 2 повторите, начиная с № 1.

Теперь для своего кода я создал VICAirplane как простой подкласс UIView это имеет единственное свойство: @property (assign,nonatomic) CGPoint rotateToLocation,

По сути, вы пытались иметь один for цикл для перебора ваших объектов, но он будет работать лучше, если вы перебираете массив во время каждой анимации. Вы можете определенно объединить их в цепочку, как показано ниже, но вы также можете создать отдельные методы для каждой "ссылки" цепочки анимации, а затем выполнить итерацию по массиву один раз для каждого метода. В любом случае вам нужно перебирать массив в / во время блока анимации, а не за его пределами. Когда вы выполняете итерации вне этого (как ваш код делает выше), вы создаете отдельный блок анимации для каждого объекта, каждый из которых будет обрабатываться независимо.

В любом случае, приведенный ниже код создает 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) {
    }
}

Мне не нужно было вставлять петлю в моем startRepeatingAnimationForView метод и только что передал params в тот же метод

Вместо этого я должен был поставить это здесь (что я сейчас сделал и работает намного лучше, чем мой оригинал)

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

}
Другие вопросы по тегам