2012-02-14 5 views
11

У меня есть массив изображений, загружаемых в UIImageView, которые я оживляю в течение одного цикла. После того, как изображения были отображены, я хотел бы вызвать @selector, чтобы закрыть текущий контроллер. Изображения анимированы с помощью этого кода:Метод доступа после завершения анимации UIImageView

NSArray * imageArray = [[NSArray alloc] initWithObjects: 
         [UIImage imageNamed:@"HowTo1.png"], 
         [UIImage imageNamed:@"HowTo2.png"], 
         nil]; 
UIImageView * instructions = [[UIImageView alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 

instructions.animationImages = imageArray; 
[imageArray release]; 
instructions.animationDuration = 16.0; 
instructions.animationRepeatCount = 1; 
instructions.contentMode = UIViewContentModeBottomLeft; 
[instructions startAnimating]; 
[self.view addSubview:instructions]; 
[instructions release]; 

После 16 секунд я хотел бы назвать метод. Я рассмотрел метод класса UIViewsetAnimationDidStopSelector:, но я не могу заставить его работать с моей текущей реализацией анимации. Какие-либо предложения?

Спасибо.

ответ

22

Использование performSelector:withObject:afterDelay::

[self performSelector:@selector(animationDidFinish:) withObject:nil 
    afterDelay:instructions.animationDuration]; 

или использовать dispatch_after:

dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, instructions.animationDuration * NSEC_PER_SEC); 
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ 
    [self animationDidFinish]; 
}); 
+0

Я пошел с первым методом, спасибо. –

+0

Этот метод работает нормально, спасибо rob! Но мне было интересно, что произойдет, если по какой-то причине падение частоты кадров iPhone значительно. Давайте скажем от 30 до 15. В этом случае анимация не будет закончена, когда таймер отправки будет работать правильно? – Tieme

+0

Почему, по вашему мнению, снижение частоты кадров приведет к увеличению продолжительности анимации? Возможно, изображение обращает кадры, если оно не может идти в ногу. –

3

Вы можете создать таймер для стрельбы после продолжительности вашей анимации. Обратный вызов может обрабатывать вашу логику, которую вы хотите выполнить после завершения анимации. В своем обратном вызове обязательно проверьте статус анимации [UIImageView isAnimating] на всякий случай, если вам нужно больше времени, чтобы завершить анимацию.

1

в ImageView.m

- (void) startAnimatingWithCompleted:(void (^)(void))completedHandler { 
if (!self.isAnimating) { 
    [self startAnimating]; 
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, self.animationDuration * NSEC_PER_SEC); 
    dispatch_after(popTime, dispatch_get_main_queue(),completedHandler);  
}} 
8

Там нет никакого способа сделать это именно с UIImageView. Использование задержки будет работать большую часть времени, но может возникнуть некоторое отставание после запуска. Вызывается, когда анимация происходит на экране, поэтому она неточна. Вместо использования UIImageView для этой анимации попробуйте использовать CAKeyframeAnimation, которая вызовет метод делегата, когда анимация будет закончена. Что-то вдоль этих линий:

NSArray * imageArray = [[NSArray alloc] initWithObjects: 
        (id)[UIImage imageNamed:@"HowTo1.png"].CGImage, 
        (id)[UIImage imageNamed:@"HowTo2.png"].CGImage, 
        nil]; 
UIImageView * instructions = [[UIImageView alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 

//create animation 
CAKeyframeAnimation *anim = [CAKeyframeAnimation animation]; 
[anim setKeyPath:@"contents"]; 
[anim setValues:imageArray]; 

[anim setRepeatCount:1]; 
[anim setDuration:1]; 
anim.delegate = self; // delegate animationDidStop method will be called 

CALayer *myLayer = instructions.layer; 

[myLayer addAnimation:anim forKey:nil]; 

Тогда просто реализовать метод animationDidStop делегат

+0

Невозможно добавить CGImage в массив. –

+0

Чтобы избавиться от предупреждения, вызванного добавлением CGImage в массив, просто введите его в id. –

+0

Ответ отредактирован, чтобы отразить выше. См. [Apples doc] (https://developer.apple.com/library/mac/documentation/GraphicsImaging/Reference/CAKeyframeAnimation_class/Introduction/Introduction.html#//apple_ref/occ/instp/CAKeyframeAnimation/values). –

4

С помощью этого метода вы избежать таймеры стрелять в то время как ImageView еще анимировать из-за медленной загрузки изображений. Вы можете использовать как performSelector: withObject: afterDelay: и НОД таким образом:

[self performSelector:@selector(didFinishAnimatingImageView:) 
      withObject:imageView 
      afterDelay:imageView.animationDuration]; 

/\self.imageView.animationDuration имеет Чтобы сделать ставку, сконфигурирован до startAnimating, в противном случае он будет 0

чем если -(void)didFinishAnimatingImageView: создать фоновые очереди, выполните Проверкой isAnimating собственности, чем выполнить остальные на главной очереди

- (void)didFinishAnimatingImageView:(UIImageView*)imageView 
{ 

    dispatch_queue_t backgroundQueue = dispatch_queue_create("com.yourcompany.yourapp.checkDidFinishAnimatingImageView", 0); 
    dispatch_async(backgroundQueue, ^{ 

     while (self.imageView.isAnimating) 
      NSLog(@"Is animating... Waiting..."); 

     dispatch_async(dispatch_get_main_queue(), ^{ 

      /* All the rest... */ 

     }); 

    }); 

} 
+0

Простое решение, работает как шарм –

20

Вы можете s реали использование этой категории UIImageView-AnimationCompletionBlock

И Swift версии: UIImageView-AnimationImagesCompletionBlock

Взгляните на ReadMe файл в этом классе ..

Добавить UIImageView + AnimationCompletion.h и UIImageView + AnimationCompletion.м файлов проект и их импорт UIImageView + AnimationCompletion.h файла, в котором вы хотите использовать это ..

Для например.

NSMutableArray *imagesArray = [[NSMutableArray alloc] init]; 
for(int i = 10001 ; i<= 10010 ; i++) 
    [imagesArray addObject:[UIImage imageNamed:[NSString stringWithFormat:@"%d.png",i]]]; 

self.animatedImageView.animationImages = imagesArray; 
self.animatedImageView.animationDuration = 2.0f; 
self.animatedImageView.animationRepeatCount = 3; 
[self.animatedImageView startAnimatingWithCompletionBlock:^(BOOL success){ 
NSLog(@"Animation Completed",);}]; 
+0

Спасибо! Отлично. – daspianist

+0

Это должен быть принятый ответ – 2cupsOfTech

+0

Я не могу понять, как использовать это в быстром. После добавления в заголовок заголовок все еще не работает. –

0

Создано Swift Версия от GurPreet_Singh Ответ (UIImageView + AnimationCompletion) я не был в состоянии создать расширение для UIImageView, но я считаю, что это достаточно простой в использовании.

class AnimatedImageView: UIImageView, CAAnimationDelegate { 

    var completion: ((_ completed: Bool) -> Void)? 

    func startAnimate(completion: ((_ completed: Bool) -> Void)?) { 
     self.completion = completion 
     if let animationImages = animationImages { 
      let cgImages = animationImages.map({ $0.cgImage as AnyObject }) 
      let animation = CAKeyframeAnimation(keyPath: "contents") 
      animation.values = cgImages 
      animation.repeatCount = Float(self.animationRepeatCount) 
      animation.duration = self.animationDuration 
      animation.delegate = self 

      self.layer.add(animation, forKey: nil) 
     } else { 
      self.completion?(false) 
     } 
    } 

    func animationDidStop(_ anim: CAAnimation, finished flag: Bool) { 
     completion?(flag) 
    } 
} 


let imageView = AnimatedImageView(frame: CGRect(x: 50, y: 50, width: 200, height: 135)) 
imageView.image = images.first 
imageView.animationImages = images 
imageView.animationDuration = 2 
imageView.animationRepeatCount = 1 
view.addSubview(imageView) 

imageView.startAnimate { (completed) in 
    print("animation is done \(completed)") 
    imageView.image = images.last 
}