How to play videos in iOS 9

Until iOS 8 we could use the trusty old MPMoviePLayerViewController class to play videos on our devices, but that’s been deprecated in iOS 9. From now on, Apple recommend we use the AVPlayerViewController class instead. It has many advantages and even supports picture-in-picture out of the box.

Although AVPlayerViewController is a subclass of UIViewController, instances of it cannot be presented using presentViewController – but Apple make sure not to mention this little tidbit. It’s much more “fun” to figure this out on our own.

Here’s how we can use it with a local video from the main bundle:

@import AVFoundation;
@import AVKit;

// ...

// grab a local URL to our video
NSURL *videoURL = [[NSBundle mainBundle]URLForResource:@"video" withExtension:@"mp4"];

// create an AVPlayer
AVPlayer *player = [AVPlayer playerWithURL:videoURL];

// create a player view controller
AVPlayerViewController *controller = [[AVPlayerViewController alloc]init];
controller.player = player;
[player play];

// show the view controller
[self addChildViewController:controller];
[self.view addSubview:controller.view];
controller.view.frame = self.view.frame;

First we grab a URL to either a local or remote video. Next we create an AVPlayer with this URL, and add said player to the newly created AVPlayerViewController instance. You can auto-play a video by using the player’s play method, or remove it and leave it up to the user to start the video.

Next we’ll present the controller by adding it as a subview to our current view, making sure it has the same frame size.

The class works equally well with local and remote URLs. To play a remote asset, construct the URL like this:

NSURL *videoURL = [NSURL URLWithString:@"https://github.com/versluis/Movie-Player/blob/master/Movie%20Player/video.mov?raw=true"];




10 thoughts on “How to play videos in iOS 9

  1. I am not sure why you say that. I have presented AVPlayerViewController instances on my controllers, and they present just as expected. It’s a much better (i.e. familiar) API than the old MPMoviePLayerViewController API, which required special category to present.

  2. Thank you, worked great for me!

    However there are two things I’m having trouble with:
    1. When the video has finished playing it doesn’t close (unless i press done). Is it possible to automatically close the video when it reaches the end and go back to the view where I pressed the button to start playing the video?
    2. Also, when I do press “done” it returns to the start page of the app, and not the previous page where I have to buttons to start the video.

    I’m a beginner at this, but I hope you understand what I mean and that you maybe have a solution 🙂

    1. Hi Johan, very good questions indeed. I’m wondering that myself 😉 Usually there’s either a block or delegate that’s called when such methods have finished, in which you can react accordingly. I’ve not seen this here – I’ll look into it though and let you know when I find a solution by adding a comment here.

  3. I’m greatful for this; works great! One question: I’ve set the controller view to controller.view.frame = CGRectMake(0,25, 750, 422); so you can switch from little screen to full screen. Works great. But when watching in full screen I want the view to jump back to little view when done, without having to press ‘Done’. Anyone??

  4. I know it’s been a while, but I’ve finally found a way on how to react to the end of the video. It’s a notification we can make use of, called name: AVPlayerItemDidPlayToEndTimeNotification.

    // register notificaton for end of movie
        [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(repeatVideo:) name:AVPlayerItemDidPlayToEndTimeNotification object:self.playerView.player.currentItem];
    

    Once registered, add a method and do whatever you like, for example start playing the same video again:

    - (void)repeatVideo:(NSNotification *)notification {
        
        // react by setting the video back to 0
    
        [self.playerView.player seekToTime:kCMTimeZero];
        
        // then play it again
        [self.playerView.player play];
    }
    

    Or do anything else you need, for example make your view small again. The notification does contain the player object.

    We can even do the whole thing as a (totally unreadable) block, in which code can be defined in the notification registration. For completion:

    // register notification using a block
    
    [[NSNotificationCenter defaultCenter]addObserverForName:AVPlayerItemDidPlayToEndTimeNotification object:self.playerView.player queue:nil usingBlock:^(NSNotification * _Nonnull note) {
        
        // your "end of video" code goes here
        [self.playerView.player seekToTime:kCMTimeZero];
        [self.playerView.player play];
    }];
    

    Hope this helps!

Leave a Reply