Как запустить несколько блоков 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 длины, анимация работает отлично.
Но если я добавлю несколько анимаций, все они будут одинаковыми по времени, и они начнут терять законченное состояние и в итоге получат много беспорядка.
Что я хотел бы сделать, это:
- Перебрать мои 5 изображений
- Выполнить мой поворот -> переместить -> повторить (навсегда) анимацию на каждом изображении
Но я не уверен, как заставить это работать для нескольких представлений uiimage, сохраненных в массиве
Есть ли способ сделать это?
2 ответа
Если я правильно понимаю ваш вопрос, следующий код должен делать то, что вы хотите. Он предназначен для выполнения следующих действий в указанном порядке:
- Поверните все элементы в виде / самолете / любом массиве в их новые вращения одновременно и в течение той же продолжительности.
- Переведите все элементы вида / самолета / любого массива в их новые местоположения одновременно и в течение той же продолжительности.
- В конце № 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];
}
}
}];
}
}];
}