2012-02-14 29 views
11

Mam wiele obrazów załadowanych do UIImageView, które animuję w jednym cyklu. Po wyświetleniu obrazów chciałbym wywołać @selector, aby odrzucić bieżący kontroler widoku. Obrazy są animowane dobrze z tym kodem:Metoda dostępu Po zakończeniu wyświetlania animacji 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]; 

Po 16 sekundach chciałbym wywołać metodę. Sprawdziłem metodę klasy UIView klasy setAnimationDidStopSelector:, ale nie mogę jej uruchomić z moją obecną implementacją animacji. Jakieś sugestie?

Dzięki.

Odpowiedz

22

Zastosowanie performSelector:withObject:afterDelay::

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

lub użyj 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

Poszedłem z pierwszą metodą, dzięki. –

+0

Ta metoda wydaje się działać dobrze, dzięki rob! Ale zastanawiałem się, co by się stało, gdyby z jakiegoś powodu spadek liczby klatek na sekundę iPhone'a był dużo. Powiedzmy, że od 30 do 15. W takim przypadku animacja nie zakończyłaby się, gdy timer wysyłki wyszedłby w prawo? – Tieme

+0

Dlaczego według Ciebie spadająca liczba klatek animacji będzie trwała dłużej? Może widok obrazu porzuca klatki, jeśli nie nadąża. –

3

Możesz utworzyć timer, który będzie uruchamiany po zakończeniu animacji. Callback może przetworzyć logikę, którą chcesz wykonać po zakończeniu animacji. W swoim oddzwonieniu sprawdź stan animacji na wypadek, gdybyś potrzebował więcej czasu na zakończenie animacji.

1

w 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

Nie ma sposobu, aby to zrobić właśnie z UIImageView. Korzystanie z opóźnienia będzie działać przez większość czasu, ale może wystąpić pewne opóźnienie po wywołaniu startAnimating, zanim animacja stanie się na ekranie, więc nie jest precyzyjna. Zamiast używać UIImageView dla tej animacji, spróbuj użyć CAKeyframeAnimation, która wywoła metodę delegata po zakończeniu animacji. Coś wzdłuż tych linii:

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

Następnie wystarczy zaimplementować metodę animationDidStop delegata

+0

Nie można dodać CGImage do tablicy. –

+0

Aby pozbyć się ostrzeżenia spowodowanego przez dodanie CGImage do tablicy, wystarczy przesłać go do id. –

+0

Odpowiedź została zmodyfikowana, aby odzwierciedlić powyższe. Zobacz [apples doc] (https://developer.apple.com/library/mac/documentation/GraphicsImaging/Reference/CAKeyframeAnimation_class/Introduction/Introduction.html#//apple_ref/occ/instp/CAKeyframeAnimation/values). –

4

Dzięki tej metodzie możesz uniknąć czasomierze na ogień, gdy ImageView wciąż animacji ze względu na powolne ładowanie obrazu. Można użyć zarówno performSelector: withObject: afterDelay: i GCD w ten sposób:

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

/\self.imageView.animationDuration ma postawić skonfigurowane przed startAnimating, w przeciwnym razie będzie to 0

niż gdyby -(void)didFinishAnimatingImageView: utworzyć kolejkę tła, należy wykonać czek na posesji isAnimating, niż wykonać resztę na głównej kolejki

- (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

Proste rozwiązanie, działa jak wdzięk –

20

można s Zastosowanie wyko tej kategorii UIImageView-AnimationCompletionBlock

I Swift wersji: UIImageView-AnimationImagesCompletionBlock

spojrzeć na plik ReadMe w tej klasie ..

Dodaj UIImageView + AnimationCompletion.h i UIImageView + AnimationCompletion.m pliki w projekcie i ich importowanie UIImageView + AnimationCompletion.h plik, w którym chcesz go użyć.

Na przykład.

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

Dziękujemy! To jest świetne. – daspianist

+0

to powinna być zaakceptowana odpowiedź. – 2cupsOfTech

+0

Nie mogę wymyślić, jak użyć tego w szybkim tempie. Po dodaniu do nagłówka pomostowego nadal nie działa. –

0

Utworzono Swift Wersja z GurPreet_Singh Odpowiedź (UIImageView + AnimationCompletion) nie byłem w stanie stworzyć rozszerzenie dla UIImageView ale wierzę, że jest to dość proste w użyciu.

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 
} 
Powiązane problemy