Método de access após terminar animação UIImageView

Eu tenho uma matriz de imagens carregadas em um UIImageView que estou animando em um ciclo. Após as imagens terem sido exibidas, eu gostaria que um @selector fosse chamado para descartar o controlador de exibição atual. As imagens são animadas com este código:

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

Após os 16 segundos, gostaria que um método fosse chamado. Eu olhei para o método de class UIView setAnimationDidStopSelector: mas não consigo fazê-lo funcionar com a minha implementação de animação atual. Alguma sugestão?

Obrigado.

Use performSelector:withObject:afterDelay: ::

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

ou use o 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]; }); 

Você pode simples usar esta categoria UIImageView-AnimationCompletionBlock

E para a versão Swift : UIImageView-AnimationImagesCompletionBlock

Dê uma olhada no arquivo LeiaMe desta class.

Adicione os arquivos UIImageView + AnimationCompletion.he UIImageView + AnimationCompletion.m no projeto e importe o arquivo UIImageView + AnimationCompletion.h onde você deseja usar isto.

Por exemplo

 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",);}]; 

Não há como fazer isso precisamente com o UIImageView. Usar um atraso funcionará na maior parte do tempo, mas pode haver algum atraso após startAnimating é chamado antes que a animação aconteça na canvas, portanto, não é preciso. Em vez de usar o UIImageView para essa animação, tente usar um CAKeyframeAnimation que chamará um método delegate quando a animação for concluída. Algo ao longo destas linhas:

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

Em seguida, basta implementar o método delegado animationDidStop

Com esse método, você evita que os timers disparem enquanto o imageView ainda está sendo animado devido ao carregamento lento da imagem. Você poderia usar tanto performSelector: withObject: afterDelay: e GCD desta maneira:

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

/! \ self.imageView.animationDuration tem que apostar configurado antes de startAnimating , caso contrário será 0

Do que se -(void)didFinishAnimatingImageView: crie uma fila em segundo plano, execute uma verificação na propriedade isAnimating , em vez de executar o resto na fila principal

 - (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... */ }); }); } 

Você pode criar um timer para triggersr após a duração da sua animação. O retorno de chamada pode processar sua lógica que você deseja executar após a conclusão da animação. Em seu retorno de chamada, verifique o status da animação [UIImageView isAnimating] caso queira mais tempo para deixar a animação terminar.

Criado a versão Swift da resposta GurPreet_Singh (UIImageView + AnimationCompletion) Eu não era capaz de criar uma extensão para UIImageView, mas acredito que isso é simples o suficiente para usar.

 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 } 

em 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); }}