NSNotification中的观察者(itemDidFinishPlaying)随机调用两次

时间:2013-04-27 04:51:24

标签: ios objective-c uitextview avplayer nsnotification

视频播放完毕后,我正在显示文字。我正在使用通知技术来实现这一目标。唯一的问题是Observer每隔一段时间被调用两次。它触发“itemDidFinishPlaying”两次(因此同名的方法)。我无法预测何时。我不知道为什么。它看起来是随机的(我知道这听起来很奇怪)就好像它工作得很好让我们说连续15次,然后下一次这种行为突然发生了。我做了一个重建并运行应用程序,这次它连续运行19次,然后两次调用Observer等等......不可预测。我已经尝试过每个场景来预测bug以便修复它。到目前为止,这是不可能的。所以我有两个问题。

1)为什么会发生并“随机”?

2)如何解决这个双重调用问题?

此后两次对话也没有帮助:

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

How to stop the Observer in NSNotification to called twice?

请在下面找到我的代码:

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

}

3 个答案:

答案 0 :(得分:8)

试试这个,

-(void)itemDidFinishPlaying {

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

}

它可能适合你。

<强> EDIT1:

在设置新方案之前每次都删除通知观察者。尝试以下方案。它将确保删除前一个观察者(即使它不存在也没问题)并添加新的观察者。

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

答案 1 :(得分:1)

这只发生在AirPlay期间。我使用以下解决方法忽略重复通知。

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

    //Do your stuff here.
}

NSUserDefault的答案也有效,但是你必须再次添加观察者,根据你的设置可能会很复杂。

答案 2 :(得分:0)

1)确认您只有一个观察者,并且没有悬挂在未按预期分配的视图控制器中。

2)如果您确认只有一个观察者,这听起来像您可以使用跟踪变量,并且在通知的第一个实例之后忽略任何内容。不优雅,但应该可以。