0
votes

I have a UIViewController that consists of 2 halves (they're actually in UIContainerViews). 1 half contains a UIWebView, which is used to display a PDF and the other half contains a UIView which is used to stream videos.

There's a navigation bar with the UIWebView, with a UIButton which when pressed presents a modal UIWebview in fullscreen mode:

- (IBAction)pressedFullscreenButton:(id)sender
{
  // pause the video view controller
  self.videoViewController.videoPlayer pause];

  // perform the segue - this is modal, full screen
  [self performSegueWithIdentifier:@"FullscreenSegue" sender:self];
}

So i press the full screen button, the video pauses, and my pdf/uiwebview is presented in modally, fullscreen. When i dismiss this fullscreen view controller to get back to my split screen, when i press play on the video, the audio plays, but the video doesn't and i can't for the life figure out why - any help would be really appreciated.

To get round this, and this is not my preferred solution, i basically get the current time of the video, stop it, set the current time, play the video and immendiately pause it when the view controller appears. Here is my code:

So I use a MPMoviePlayerController, which i have wrapped into a class called StandardVideoPlayer:

@implementation StandardVideoPlayer


-(id)initWithParentView:(UIView *)parent andAutoPlay:(BOOL)autoPlay andFullScreen:(BOOL)fullScreen andAnimated:(BOOL)animated
{
  // Call superclass's initializer
  self = [super init];
  if( !self || !parent)
  {
    return nil;
  }
  else
  {
    if (!_moviePlayerController)
    {
      _moviePlayerController = [[MPMoviePlayerController alloc] init];
    }

    _moviePlayerController.controlStyle = MPMovieControlStyleDefault;
    [_moviePlayerController.view setFrame:parent.frame];
    [_moviePlayerController.view setCenter:parent.center];
    _moviePlayerController.allowsAirPlay = YES;
    _moviePlayerController.shouldAutoplay = autoPlay;
    [_moviePlayerController setFullscreen:fullScreen animated:animated];

    [parent addSubview: [self videoView]];
  }

  return self;
}

-(void)loadFromFile: (NSString*) filePath;
{
  if (_moviePlayerController)
  {
    NSURL *fileUrl = [NSURL fileURLWithPath:filePath];
    [_moviePlayerController setContentURL:fileUrl];
    [_moviePlayerController prepareToPlay];
  }
}

- (void)loadFromURL: (NSString*) urlString
{
  if ( [[ConnectionManager sharedInstance] canConnect] )
  {
    if (_moviePlayerController)
    {
      NSURL *url = [NSURL URLWithString:urlString];
      [_moviePlayerController setContentURL:url];
      [_moviePlayerController prepareToPlay];
    }
  }
  else
  {
    [[ConnectionManager sharedInstance] displayConnectionWarningWithText:@"Ok" andDelegate:nil];

  }

}

-(void)loadFromHTML:(NSString *)html
{
  // NSString *h = [NSString stringWithFormat:html, ]
}

-(void)play
{
  if (_moviePlayerController)
  {
    [_moviePlayerController prepareToPlay];
    [_moviePlayerController play];
  }
}

-(void)stop
{
  if (_moviePlayerController)
  {
    [_moviePlayerController stop];
  }
}

-(void)pause
{
  if (_moviePlayerController)
  {
    [_moviePlayerController pause];
  }
}

// use this to get the view form the moviePlayerController......
-(UIView*)videoView
{
  UIView *view = nil;
  if (_moviePlayerController)
  {
    view = _moviePlayerController.view;
  }

  return view;
}


@end

and then in the view controller i have:

@implementation VideoViewController

// lazy initialiser
- (StandardVideoPlayer*) videoPlayer
{
  if (!_videoPlayer)
  {
    _videoPlayer = [[StandardVideoPlayer alloc] initWithParentView:self.view andAutoPlay:NO andFullScreen:NO andAnimated:YES];
  }
  return _videoPlayer;
}

- (void) viewDidLoad
{
  [super viewDidLoad];

  self.initialised = NO;
  self.wasPDFScreen = NO;
  self.isFullScreen = NO;
  [self.spinner stopAnimating];
  self.spinner.hidesWhenStopped = YES;

  [GlobalStore sharedInstance].videoViewController = self;
}

-(void) willEnterFullScreen
{
  self.isFullScreen = YES;
}

-(void)loadStateChanged
{
  MPMovieLoadState state = [self.videoPlayer.moviePlayerController loadState];
  if (state & MPMovieLoadStatePlayable)
  {
    [self.spinner stopAnimating];
  }
}

-(void) customInit
{
  if (!self.initialised)
  {        
    [self.view setBackgroundColor:[UIColor blackColor]];
    [self.videoPlayer.videoView setBackgroundColor:[UIColor blackColor]];

    // set a border
    CGFloat borderWidth = 1.0f;

    self.videoPlayer.videoView.frame = CGRectInset(self.videoPlayer.videoView.frame, -borderWidth, -borderWidth);
    self.videoPlayer.videoView.layer.borderColor = BORDER_COLOUR;
    self.videoPlayer.videoView.layer.borderWidth = borderWidth;

    self.view.frame = CGRectInset(self.view.frame, -borderWidth, -borderWidth);
    self.view.layer.borderColor = BORDER_COLOUR;
    self.view.layer.borderWidth = borderWidth;

    // set this to be able to exit the video player properly
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(willEnterFullScreen)
                                                 name:MPMoviePlayerWillEnterFullscreenNotification
                                               object:_videoPlayer.moviePlayerController];

    // set this to be able to start/stop the spinner
 [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(loadStateChanged)
                                                 name:MPMoviePlayerLoadStateDidChangeNotification
                                               object:_videoPlayer.moviePlayerController];

    // make sure the views are always at the front
    [self.view bringSubviewToFront:self.videoPlayer.videoView];
    [self.view bringSubviewToFront:self.spinner];

    self.initialised = YES;
  }
}

-(void)viewDidAppear:(BOOL)animated
{
  [super viewDidAppear:animated];

  [self customInit];
}

-(void) viewWillAppear:(BOOL)animated
{
  [super viewWillAppear:animated];

  [self.spinner stopAnimating];

  if (_videoPlayer && self.wasPDFScreen)
  {
    NSTimeInterval time = [self.videoPlayer.moviePlayerController currentPlaybackTime];
    if (time != 0)
    {
      // So to ge the video to play properly, i have to uncommment the lines below, but this loses the cache and isn't quite as smooth as i would like.

      //[self stopVideo];
      //self.videoPlayer.moviePlayerController.currentPlaybackTime = time;
      //[self.videoPlayer.moviePlayerController prepareToPlay];
      //[self.videoPlayer.moviePlayerController play];
      //[self.videoPlayer.moviePlayerController pause];
    }
  }

  self.isFullScreen = NO;
  self.wasPDFScreen = NO;
}

-(void)viewDidDisappear:(BOOL)animated
{
  [super viewDidDisappear:animated];

  // only stop the video when we mean to - not when we go into full screen mode
  if (!self.isFullScreen && !self.wasPDFScreen)
    [self stopVideo];
}

- (void)playVideo
{
  [self.spinner startAnimating];

    [self.videoPlayer loadFromURL:@"someurl"];    

    // and play!!
    [self.videoPlayer play]; 
}

-(void)stopVideo
{
  [self.videoPlayer stop];
}

@end
1

1 Answers

0
votes

I ended up implementing an AV Kit View Controller instead. Works perfectly.