user717452
user717452

Reputation: 111

Stop Playback of AVPlayer item and replace with new

My app has a tableview that when selected, opens a new view controller and uses AVPlayer to start playing the URL passed to it. However, when they go back and select a new item for playback, I can't get it to stop the first, and begin playback of the second. Any suggestions?

- (void)viewWillAppear:(BOOL)animated {
        [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];

          
           [[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
           [self becomeFirstResponder];
           NSURL *newURL = [NSURL URLWithString:_entry.articleUrl];
          
           AVPlayer *player = [AVPlayer playerWithURL:newURL];
    
            _controller = [[AVPlayerViewController alloc]init];
            _controller.player = player;
        
            
           
            // show the view controller
            [self addChildViewController:_controller];
            [self.view addSubview:_controller.view];
            _controller.view.frame = self.view.frame;
    [player play];
   
    self.title = _entry.articleTitle;
   
    

    [super viewWillAppear:YES];
}

Upvotes: 0

Views: 789

Answers (1)

skaak
skaak

Reputation: 3018

EDIT I've changed this to return the player when you message startPlaying - that way it is real easy to update your controller as discussed in the comments.

Here is an outline that may work - did not test it but hopefully it will solve your problem.

Header file should contain

@interface MyPlayer : NSObject

// Start playing some URL and return the player
+ ( AVPlayer * ) startPlaying:( NSURL * ) url;

@end

And in m file, very similar to before,

#import <AVKit/AVKit.h>
#import "MyPlayer.h"

@interface MyPlayer ()

@property (nonatomic,strong) NSObject * playerLock;
@property (nonatomic,strong) AVPlayer * player;

@end

@implementation MyPlayer

// Initialise
- ( id ) init
{
    self = super.init;

    if ( self )
    {
        self.playerLock = NSObject.new;
    }

    return self;
}

// Return singleton
+ ( MyPlayer * ) myPlayer
{
    static MyPlayer * mp;
    static dispatch_once_t t;

    dispatch_once ( & t, ^ {

        mp = [[MyPlayer alloc] init];

    } );

    return mp;
}

// Start playing some URL and return the player
+ ( AVPlayer * ) startPlaying:( NSURL * ) url
{
    MyPlayer * mp = MyPlayer.myPlayer;
    AVPlayer * player;

    @synchronized ( mp.playerLock )
    {
        if ( mp.player )
        {
            // Replace
            [mp.player replaceCurrentItemWithPlayerItem:[AVPlayerItem playerItemWithURL:url]];
        }
        else
        {
            // Create a new player
            mp.player = [AVPlayer playerWithURL:url];
        }
        
        player = mp.player;
    }

    // Start playing on a background thread
    dispatch_async ( dispatch_get_global_queue ( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0 ), ^ {

        @synchronized ( mp.playerLock )
        {
            // Start playing
            mp.player.play;
        }

    } );

    return player;
}

@end

Just message [MyPlayer startPlaying:url]; to play a URL as before, but this time, it will return the player.

So in your code you can do something like

_controller.player = [MyPlayer startPlaying:url];

Upvotes: 1

Related Questions