如何关闭以前的AVPlayer和AVPlayerItem

我在Swift中制作了一个iOS应用程序,它在屏幕右上角的一个小层中循环播放video,显示特定彩色项目的video。 然后用户点击屏幕上相应的彩色项目。 当它们执行时,videoName变量随机更改为下一个颜色,并触发相应的video。 使用AVPlayer,AVPlayerItem来提升,播放和循环video没有问题,如附带的代码所示。 我被困的地方是,无论何时显示下一个video,之前的video都会在它后面保持打开状态。 此外,播放了16个video后,播放器完全消失在我的iPad上。 我已尝试过在本网站和其他网站上提出的许多建议,但要么swift发现它们有问题,要么就是不起作用。 所以问题:在我的代码中,我怎么告诉它“嘿,下一个video已经开始播放,删除以前的video及其层,释放内存,以便我可以根据需要播放尽可能多的video”?

//set variables for video play var playerItem:AVPlayerItem? var player:AVPlayer? //variables that contain video file path, name and extension var videoPath = NSBundle.mainBundle().resourcePath! var videoName = "blue" let videoExtension = ".mp4" //DISPLAY VIDEO func showVideo(){ //Assign url path let url = NSURL(fileURLWithPath: videoPath+"/Base.lproj/"+videoName+videoExtension) playerItem = AVPlayerItem(URL: url) player=AVPlayer(playerItem: playerItem!) let playerLayer=AVPlayerLayer(player: player!) //setplayser location in uiview and show video playerLayer.frame=CGRectMake(700, 5, 350, 350) self.view.layer.addSublayer(playerLayer) player!.play() // Add notification to know when the video ends, then replay it again. THIS IS A CONTINUAL LOOP NSNotificationCenter.defaultCenter().addObserverForName(AVPlayerItemDidPlayToEndTimeNotification, object: player!.currentItem, queue: nil) { notification in let t1 = CMTimeMake(5, 100); self.player!.seekToTime(t1) self.player!.play() } } 

`

我改编了@Anupam Mishra的Swift代码建议。 它最初没有工作,但最终认为我必须将playerLayer带到该function之外并在我将玩家设置为nil之后关闭playerLayer。 也。 而不是使用’if(player!.rate> 0 …)’毫无疑问仍然可以工作,我创建了一个变量开关来指示何时说“杀死玩家和层”,如下所示。 它可能不漂亮,但它的工作原理! 以下是像我这样的绝对新手 – 我从这次经历中学到了什么:在我看来,ios设备只允许将16层添加到viewController(或superLayer)。 因此,在使用其播放器打开下一层之前,需要删除每一层,除非您确实希望一次运行16层。 这个代码实际上对你来说是什么:这个代码在现有的viewController上创建一个可resize的层,并在无限循环中播放你的包中的video。 当即将调用下一个video时,将完全删除当前video和图层,释放内存,然后播放带有新video的新图层。 video图层大小和位置可使用playerLayer.frame = CGRectMake(左,顶部,宽度,高度)参数完全自定义。 如何完成所有工作:假设您已经将video添加到捆绑包中,请为按钮点击创建另一个function。 在该函数中,首先调用’stopPlayer()’函数,将’videoName’变量更改为您想要的新video名称,然后调用’showVideo()’函数。 (如果您需要更改video扩展名,请将’videoExtension’从let更改为var。

`

 //set variables for video play var playerItem:AVPlayerItem? var player:AVPlayer? var playerLayer = AVPlayerLayer() //NEW playerLayer var location //variables that contain video file path, name and extension var videoPath = NSBundle.mainBundle().resourcePath! var videoName = "blue" let videoExtension = ".mp4" var createLayerSwitch = true /*NEW switch to say whether on not to create the layer when referenced by the closePlayer and showVideo functions*/ //DISPLAY VIDEO func showVideo(){ //Assign url path let url = NSURL(fileURLWithPath: videoPath+"/Base.lproj/"+videoName+videoExtension) playerItem = AVPlayerItem(URL: url) player=AVPlayer(playerItem: playerItem!) playerLayer=AVPlayerLayer(player: player!) //NEW: remove 'let' from playeLayer here. //setplayser location in uiview and show video playerLayer.frame=CGRectMake(700, 5, 350, 350) self.view.layer.addSublayer(playerLayer) player!.play() createLayerSwitch = false //NEW switch to tell if a layer is already created or not. I set the switch to false so that when the next tapped item/button references the closePlayer() function, the condition is triggered to close the player AND the layer // Add notification to know when the video ends, then replay it again without a pause between replays. THIS IS A CONTINUAL LOOP NSNotificationCenter.defaultCenter().addObserverForName(AVPlayerItemDidPlayToEndTimeNotification, object: player!.currentItem, queue: nil) { notification in let t1 = CMTimeMake(5, 100); self.player!.seekToTime(t1) self.player!.play() } } //NEW function to kill the current player and layer before playing the next video func closePlayer(){ if (createLayerSwitch == false) { player!.pause() player = nil playerLayer.removefromsuperlayer() } } 

`

为什么不在你的播放器上使用replaceCurrentItemWithPlayerItem ? 您将为所有video保留相同的播放器。 我认为这是一种更好的方法。

编辑:必须在主线程上调用replaceCurrentItemWithPlayerItem

在进行下一首曲目首先检查之前,玩家是否有任何video或音乐,要阻止它进行以下检查 –

SWIFT代码-

 if (player!.rate>0 && player!.error == nil) { player!.pause(); player = nil } 

Objective-C代码 –

 if (player.rate>0 && !player.error) { [player setRate:0.0]; }