iOS 7 MPMoviePlayerController seek forward button

2020-08-13 02:23发布

问题:

I am facing an issue with MPMoviePlayerController in iOS 7. I enter the fullscreen and then click (just a single tap) on seek forward button (>>|) , and the video playback ends and gives a black screen with a text "Loading" on the header.

I registered notification for "MPMoviePlayerPlaybackStateDidChangeNotification".

**[[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(moviePlayerPlaybackStateDidChange:)
                                                 name:MPMoviePlayerPlaybackStateDidChangeNotification
                                               object:self.player];**

It does not get fired on a single click of seek forward button.

Also on registration of "MPMoviePlayerPlaybackDidFinishNotification"

**[[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(moviePlayerPlaybackDidFinish:)
                                                 name:MPMoviePlayerPlaybackDidFinishNotification
                                               object:nil];**

I get "MPMovieFinishReasonPlaybackEnded" event fired on that single click of seek forward button. Any one knows the reason why? Is this a bug in apple?

I need to either stop this behavior of showing a black screen on single click , or just disable single click of seek forward button so that nothing happens.

Any one knows how to achieve this?

回答1:

I fixed this by removing the MPMoviePlayer object completely, setting it to nil, removing it from it's superview and re-adding it using the original video Url. Code below:

- (void)addPlayerForUrl:(NSURL *)url {
  self.player = [[MPMoviePlayerController alloc] initWithContentURL:url];
  self.player.view.frame = self.videoView.bounds;
  self.player.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
  self.player.controlStyle = MPMovieControlStyleDefault;
  [self.videoView insertSubview:self.player.view atIndex:0];

  [[NSNotificationCenter defaultCenter] addObserver:self
                                           selector:@selector(moviePlayerLoadStateDidChangedNotification:)
                                               name:MPMoviePlayerReadyForDisplayDidChangeNotification
                                             object:self.player];

  [[NSNotificationCenter defaultCenter] addObserver:self
                                           selector:@selector(moviePlayerPlaybackStateDidChangeNotification:)
                                               name:MPMoviePlayerPlaybackStateDidChangeNotification
                                             object:self.player];
}


#pragma mark - Notifications

- (void)moviePlayerLoadStateDidChangedNotification:(NSNotification *)notification {
  self.isVideoPreloaded = YES;
  self.videoPlayButton.hidden = YES;
  self.photoImageView.hidden = YES;
  self.videoLoadingImageView.hidden = YES;
}
- (void)moviePlayerPlaybackStateDidChangeNotification:(NSNotification *)notification {
      NSURL *url = self.player.contentURL;
      switch (self.player.playbackState) {
        case MPMoviePlaybackStateSeekingBackward:
        case MPMoviePlaybackStateSeekingForward:
          break;
        case MPMoviePlaybackStatePlaying:
          self.videoPlayButton.hidden = YES;

          if (!self.isVideoPreloaded) {
            self.videoLoadingImageView.hidden = NO;
            [self.videoLoadingImageView startAnimating];
          } else {
            self.videoLoadingImageView.hidden = YES;
          }
          break;
        case MPMoviePlaybackStatePaused:
        case MPMoviePlaybackStateStopped:
          self.videoPlayButton.hidden = NO;
          self.videoLoadingImageView.hidden = YES;
          [self.player endSeeking];
          [self.player.view removeFromSuperview];
          [self.player setFullscreen:NO];
          self.player = nil;
          [self addPlayerForUrl:url];
          break;
        default:
          break;
      }
    }

Notice how I keep the NSURL, right before the switch statement in the moviePlayerPlaybackStateDidChangeNotification. That way, I can re-initialize and re-add the MPMoviePlayer object.

Btw, my mpmovieplayer is on a tableviewCell if you're wondering. Hope this helps and let me know if you have questions. Good luck!



回答2:

MPMoviePlayerLoadStateDidChangeNotification will be called when you single tap on the fast-forward or rewind button. You should check the loadState and just give it the path to your video and prepareToPlay again.

- (void)moviePlayerLoadStateChanged:(NSNotification *)notification {

    MPMoviePlayerController *moviePlayer = notification.object;
    MPMovieLoadState loadState = moviePlayer.loadState;

    if(loadState == MPMovieLoadStateUnknown) {
        moviePlayer.contentURL = [NSURL fileURLWithPath:videoPath]
        [moviePlayer prepareToPlay];
    }

    .....
}


回答3:

The reason you're getting MPMovieFinishReasonPlaybackEnded is because playback reached the end of the video (sorry if this is obvious). So it seem's your seek forward actions are seeking all the way to the end of the video. You can check the playback state with MPMoviePlaybackStateSeekingForward.

A quick solution could be to create your own forward button that seek's ahead by a specified time (ie. 5 seconds). But perhaps this isn't the functionality you're looking for.