Reputation: 111
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
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