Метод доступа после завершения анимации UIImageView

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

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 секунд я хотел бы вызвать метод. Я посмотрел вUIView метод классаsetAnimationDidStopSelector: но я не могу заставить его работать с моей текущей реализацией анимации. Какие-либо предложения?

Благодарю.

Ответы на вопрос(7)

UIImageView-AnimationCompletionBlock

И длястриж версия:UIImageView-AnimationImagesCompletionBlock

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

ДобавлятьUIImageView + AnimationCompletion.h а такжеUIImageView + AnimationCompletion.m файлы в проекте и их импорт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",);}];
 daspianist06 апр. 2014 г., 07:52
Спасибо! Это здорово.
 Adam Johns23 апр. 2015 г., 02:34
Я не могу понять, как использовать это по-быстрому. После добавления в заголовок моста он все еще не работает.
 mahieddine16 авг. 2015 г., 02:01
Это определенно правильный ответ, спасибо
 2cupsOfTech10 дек. 2014 г., 18:30
это должен быть принятый ответ

  если вам нужно больше времени, чтобы анимация закончилась.[UIImageView isAnimating]Создана версия Swift из ответа GurPreet_Singh (UIImageView + AnimationCompletion) Мне не удалось создать расширение для UIImageView, но я считаю, что это достаточно просто для использования.

пока imageView все еще анимируется из-за медленной загрузки изображения. Вы могли бы использовать обаperformSelector: withObject: afterDelay: и GCD таким образом:

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

/! \  должен сделать ставку настроен раньше self.imageView.animationDurationиначе будет 0startAnimatingЧем если

создайте фоновую очередь, выполните проверку-(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... */

       });

   });

}
 Alejandro Luengo08 июн. 2016 г., 10:27
Вы можете создать таймер, чтобы стрелять после продолжительности вашей анимации. Обратный вызов может обработать вашу логику, которую вы хотите выполнить после завершения анимации. При обратном звонке обязательно проверьте состояние анимации

Метод доступа после завершения анимации UIImageView

- (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);       
}}
Решение Вопроса

использование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];
});
 Kevin_TA14 февр. 2012 г., 22:48
Я пошел с первым методом, спасибо.
 Au Ris14 мар. 2013 г., 15:35
Это как раз проблема, с которой я сталкиваюсь с executeSelector и задержкой. Массив загружается слишком медленно и теряет время. Точность потеряна. Мне нужно другое решение ...
 rob mayoff18 дек. 2012 г., 09:17
Как вы думаете, почему падение частоты кадров заставило бы анимацию занять больше времени? Может быть, при просмотре изображения пропускаются кадры, если оно не в состоянии угнаться
 Tieme18 дек. 2012 г., 09:12
Этот метод, кажется, работает нормально, спасибо Роб! Но мне было интересно, что произойдет, если по какой-то причине падение частоты кадров iPhone будет большим. Допустим, от 30 до 15. В этом случае анимация не будет закончена, когда таймер отправки истечет, верно?

что я добавил, было

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
}
 Javonne Martin31 янв. 2019 г., 09:28
 отключить интерполяцию между кадрами. Это делает его похожим на GIF с низким fps.animation.calculationMode = .discreteв ImageView.m

держки будет работать большую часть времени, но после запуска startAnimating может возникнуть некоторая задержка, прежде чем анимация появится на экране, поэтому она не точная. Вместо использования 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

 Matt Green25 сент. 2013 г., 15:47
Не могу добавить CGImage в массив.
 Matt Pearcy01 окт. 2013 г., 21:33
Ответ отредактирован, чтобы отразить выше. Видетьяблоки док.
 Matt Pearcy01 окт. 2013 г., 21:21
Чтобы избавиться от предупреждения, вызванного добавлением CGImage в массив, просто приведите его к id.

Ваш ответ на вопрос