2013-04-27 31 views
5

Wyświetlam tekst zaraz po zakończeniu odtwarzania wideo. Używam techniki powiadamiania, aby to osiągnąć. Jedynym problemem jest to, że Obserwator jest wywoływany dwa razy co chwilę. Wywołuje dwukrotnie "itemDidFinishPlaying" (a zatem metodę o tej samej nazwie). Nie potrafię przewidzieć kiedy. Nie wiem dlaczego. Wygląda losowo (wiem, że to brzmi dziwnie), tak jak działa dobrze, powiedzmy 15 razy z rzędu, i następnym razem to zachowanie stanie się nieoczekiwane. Wykonuję przebudowę i uruchamiam aplikację i tym razem działa ona dobrze 19 razy z rzędu, zanim dwa razy zadzwonię do Observera, itd ... Nieprzewidywalna. Próbowałem już wszystkich scenariuszy, aby przewidzieć błąd, aby go naprawić. Dotychczas nie było to możliwe. Mam więc 2 pytania.Obserwator w NSNotification (itemDidFinishPlaying) RANDOMLY do dwukrotnego wywołania

1) Dlaczego tak się dzieje i "losowo"?

2) Jak rozwiązać problem podwójnego wywołania?

Również te 2 Następujące rozmowy nie pomogły:

Why the Observer in NSNotification called twice....?

How to stop the Observer in NSNotification to called twice?

Proszę znaleźć kod poniżej:

- (void) playAnimation: (NSString *) theString { 

UIView *thisCurrentView = self.currentView; 
UIView *thisReplacementView = [[UIView alloc] init]; 

//[avPlayer pause]; 
[self replaceView: thisCurrentView withView: thisReplacementView]; 

NSString *filepath = [[NSBundle mainBundle] pathForResource:theString ofType:@"mov"]; 
NSURL *fileURL = [NSURL fileURLWithPath:filepath]; 


// First create an AVPlayerItem 
AVPlayerItem* playerItem = [AVPlayerItem playerItemWithURL:fileURL]; 

// Subscribe to the AVPlayerItem's DidPlayToEndTime notification. 
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(itemDidFinishPlaying) name:AVPlayerItemDidPlayToEndTimeNotification object:playerItem]; 

// Pass the AVPlayerItem to a new player 
controlledPlayer = [[AVPlayer alloc] initWithPlayerItem:playerItem]; 


AVPlayerLayer *animatedLayer = [AVPlayerLayer playerLayerWithPlayer:controlledPlayer]; 


[animatedLayer setFrame:CGRectMake(0, 0, 1024, 1024)]; 
[thisReplacementView.layer addSublayer: animatedLayer]; 


// Begin playback 
[controlledPlayer play]; 

// Clear some content 
[self displayNoContent]; 

pageContent = theString; 


playingStatus = YES; 

}

- (void) itemDidFinishPlaying {

[self displayContent: pageContent]; 

}

+0

Czy dodajesz swojego obserwatora w akcji przycisku odtwarzania wideo? – NSUserDefault

+0

@NSUserDefault, bez przycisku. Po prostu przesuwam, aby nawigować. Animacja jest odtwarzana po wyświetleniu strony. – Armand

+0

gdzie to nazywasz - (void) playAnimation: (NSString *) theString method? – NSUserDefault

Odpowiedz

7

Spróbuj tego,

-(void)itemDidFinishPlaying { 

     [self displayContent: pageContent]; 
     [[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:playerItem]; 

} 

on może pracować dla Ciebie.

Edit1:

Usuń obserwatorowi powiadomienie za każdym czasie przed ustawieniem nowego one.Try poniżej scenario.It zapewni, usunąć poprzednią obserwatora (nawet nie istnieje żaden problem) i dodaje nowy.

// Subscribe to the AVPlayerItem's DidPlayToEndTime notification. 

[[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:playerItem]; 
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(itemDidFinishPlaying) name:AVPlayerItemDidPlayToEndTimeNotification object:playerItem]; 
+0

Niestety, nie wyszło. – Armand

+0

Na razie rozwiązuję go za pomocą instrukcji warunkowej, aby wydrukować tekst tylko raz. Więc jeśli powiadomienie nastąpi drugi raz z rzędu, wyświetla tylko tekst jeden raz. Nie najseksowniejsze podejście, ale na razie pozwala mi iść naprzód. – Armand

+0

Działa do tej pory z tą linią ... Dzięki [[NSNotificationCenter defaultCenter] removeObserver: self]; – Armand

1

To zdarza się tylko podczas AirPlay. Korzystam z poniższego obejścia, aby zignorować duplikat powiadomienia.

if ([notificaiton.object isEqual:self.player.currentItem] && (self.player.rate > 0)) 
{ 
    [self.player pause]; 

    //Do your stuff here. 
} 

odpowiedź NSUserDefault jest również działa, ale potem trzeba ponownie dodać obserwatorów i może być skomplikowana w zależności od konfiguracji.