Reputation: 11042
An AVPlayerItem can only ever be assigned to one AVPlayer. Once an AVPlayerItem has been added to an AVPlayer, future attempts to add it to a different AVPlayer will SIGABRT the app.
So, given an AVPlayerItem, how can you determine:
The following code demonstrates the problem reliably:
AVPlayerItem *item = [AVPlayerItem playerItemWithURL:[NSURL URLWithString:@"http://devimages.apple.com/iphone/samples/bipbop/bipbopall.m3u8"]];
AVPlayer *firstPlayer = [[AVPlayer alloc] init];
[firstPlayer replaceCurrentItemWithPlayerItem:item];
AVPlayer *secondPlayer = [[AVPlayer alloc] init];
[secondPlayer replaceCurrentItemWithPlayerItem:item];
And here's the error message:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'An AVPlayerItem cannot be associated with more than one instance of AVPlayer'
Upvotes: 15
Views: 7135
Reputation: 92345
There is a semi-legal way that might break in the future. The player item has a private method (and, it seems, variable) named _player
. You can query it like this (which technically doesn't use private API, so I think it should be AppStore-safe):
id player = [item valueForKey:@"_player"];
Upvotes: 8
Reputation: 11995
Here is an elegant solution, without private keys and associated objects. Create a custom player item:
class PlayerAwareItem {
weak var player: AVPlayer?
}
Setup a player:
let item = PlayerAwareItem(asset: asset)
let player = AVPlayer(playerItem: item)
item.player = player
Access the player whenever you have the item later (in this example we want to restart the player after stalling):
@objc func handlePlayerItemDidStall(_ notification: Notification) {
guard let playerItem = notification.object as? PlayerAwareItem,
let player = playerItem.player else { return }
player.play()
}
Upvotes: 3
Reputation: 4196
Based on Anil's answer, for a looped playback on multiple videos:
for (NSObject * obj in cachedVideos){
if ([obj isKindOfClass:[AVPlayerLayer class]]){
AVPlayerLayer * layer = (AVPlayerLayer *)obj;
if ([layer.player.currentItem isEqual:n.object]){
[layer.player seekToTime:kCMTimeZero];
[layer.player play];
break;
}
}
}
Upvotes: 0
Reputation: 7465
You can associate an AVPlayerItem
with an AVPlayer
using:
static char playerKey;
objc_setAssociatedObject(item, &playerKey, player, OBJC_ASSOCIATION_RETAIN);
and get it using:
objc_getAssociatedObject(item, &playerKey);
Upvotes: 0
Reputation: 2438
Did you try the other way round? Try accessing the details inside the item that is being played by the AVPlayer
AVPlayer *firstPlayer = [[AVPlayer alloc]init];
After which you can access firstPlayer.currentItem
.This will give you access the firstPlayer
's AVPlayerItem
.
Eg:
firstPlayer.currentItem.duration
will give you the duration of that track.
Upvotes: 3