当我在使用AVFoundation时重新加载视图时,为什么我的playerItemDidReachEnd-method被触发了两次?

hea*_*kit 1 objective-c avfoundation

我在我的avfoundation视频播放器中循环播放视频:

NSString *loopPath = @"SubView/introCycle";
NSURL *fileURL = [[NSBundle mainBundle] URLForResource:loopPath withExtension:@"mp4"];
AVURLAsset *asset = [AVURLAsset URLAssetWithURL:fileURL options:nil];
NSString *tracksKey = @"tracks";
[asset loadValuesAsynchronouslyForKeys:@[tracksKey] completionHandler:^{
    // The completion block goes here.
    //NSLog(@"asset loaded asynchronously completed!");

    // Completion handler block.
    dispatch_async(dispatch_get_main_queue(),

                   ^{
                       NSError *error;
                       AVKeyValueStatus status = [asset statusOfValueForKey:tracksKey error:&error];

                       if (![self avPlayer] && status == AVKeyValueStatusLoaded) {
                           if(![self playerItem]){
                               self.playerItem = [AVPlayerItem playerItemWithAsset:asset];
                               [self.playerItem addObserver:self forKeyPath:@"status" options:0 context:AVMoviePlayerViewControllerStatusObservationContext];
                               self.avPlayer.actionAtItemEnd = AVPlayerActionAtItemEndNone;
                               [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playerItemDidReachEnd:)
                                                                     name:AVPlayerItemDidPlayToEndTimeNotification
                                                                     object:[self.avPlayer currentItem]];
                           }
                           self.avPlayer = [AVPlayer playerWithPlayerItem:self.playerItem];
                           [self.VideoLoopView setPlayer:self.avPlayer];
                       }

                       else {
                           // You should deal with the error appropriately.
                           NSLog(@"The asset's tracks were not loaded:\n%@", [error localizedDescription]);
                       }
                   });
}];
Run Code Online (Sandbox Code Playgroud)

在循环结束时,以下方法重新启动视频

int countRounds = 0;
- (void)playerItemDidReachEnd:(NSNotification *)notification {
    *//block 1 - this is what we like*
    if (notification.object == self.playerItem) {

        countRounds++;

        [self.playerItem seekToTime:kCMTimeZero];
        [self.avPlayer play];

        }
    }
    *// block 2 - this we don't like*
    else {
        NSInteger reason = [[notification.userInfo objectForKey:AVPlayerItemDidPlayToEndTimeNotification] integerValue];
        NSLog(@"reason: %i", reason);
    }
    NSLog(@"playerItemDidReachEnd, starting round %i", countRounds);
}
Run Code Online (Sandbox Code Playgroud)

哪个工作正常.只执行块1.日志显示

MainView did load 
playerItemDidReachEnd, starting round 1 
playerItemDidReachEnd, starting round 2 
...
Run Code Online (Sandbox Code Playgroud)

然后我加载另一个视图并返回到视频循环视图.当我离开主视图时,我做了

- (void)viewDidDisappear:(BOOL)animated
{ 
    [[NSNotificationCenter defaultCenter]   removeObserver:self
                                            name:AVPlayerItemDidPlayToEndTimeNotification
                                            object:[self.avPlayer currentItem]];
    [self.avPlayer pause];
    self.avPlayer = nil;
    self.playerItem = nil;


    [super viewDidDisappear:animated];
    NSLog(@"MainView DidDisappear");
}
Run Code Online (Sandbox Code Playgroud)

当我重新加载主视图时,视频重新加载并且循环播放良好.但现在在循环结束时,执行块1和块2,记录

MainView did load (from old log above)
playerItemDidReachEnd, starting round 1 *(from old log above)*
playerItemDidReachEnd, starting round 2 *(from old log above)*
MainView DidDisappear   *(leaving the main view and loading a new one)*
MainView did load *(coming back to main view)*
reason: 0 *(block 2 is executed, triggered by what exactly? WHERE DOES THIS COME FROM?)*
playerItemDidReachEnd, starting round 2
playerItemDidReachEnd, starting round 3 *(this comes from block 1 - we like)*
reason: 0
playerItemDidReachEnd, starting round 3
playerItemDidReachEnd, starting round 4
reason: 0
playerItemDidReachEnd, starting round 4
playerItemDidReachEnd, starting round 5
Run Code Online (Sandbox Code Playgroud)

所以在循环结束时,playerItemDidReachEnd-method被触发两次.这是为什么?这来自哪里?

hea*_*kit 7

您可以通过使用避免从错误的通知器触发

if (notification.object == self.playerItem) ...
Run Code Online (Sandbox Code Playgroud)