Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Observer in NSNotification (itemDidFinishPlaying) RANDOMLY to called twice

I am displaying a text as soon as a video is done playing. I am using a notification technique to achieve that. The only problem is that the Observer is called twice every now and then. It triggers the "itemDidFinishPlaying" twice (and therefore the method of the same name). I cannot predict when. I don't know why. It looks random (I know this sounds weird) like it's working fine let's say 15 times in a row and the next time that behaviour happens out of the blue. I do a rebuild and run the app and this time it runs fine 19 times in a row before calling the Observer twice, etc... Unpredictable. I've tried every scenarios to predict the bug in order to fix it. It's been impossible so far. So I have 2 questions.

1) Why does it happen and "randomly"?

2) How to fix this double calling issue?

Also these 2 following conversations have not helped:

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

How to stop the Observer in NSNotification to called twice?

Please find my code below:

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

}

like image 884
Armand Avatar asked Apr 27 '13 04:04

Armand


2 Answers

Try this,

-(void)itemDidFinishPlaying {

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

}

It may work for you.

EDIT1:

Remove the notification observer every-time before you set the new one.Try the below scenario.It will ensure, remove the previous observer(even it doesn't exist no problem) and adds the new one.

// 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];
like image 140
NSUserDefault Avatar answered Nov 15 '22 10:11

NSUserDefault


This only happens to me during AirPlay. I'm using the following workaround to ignore the duplicate notification.

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

    //Do your stuff here.
}

NSUserDefault's answer also works but then you have to add the observers again and could be complicated depending on your setup.

like image 32
flopr Avatar answered Nov 15 '22 10:11

flopr