‘AVPlayerItem不能与多个AVPlayer实例关联’

我知道这个问题已经遍布Stack Overflow了,但是,大多数都是旧的,与我在这里要问的内容无关。

所以我有一个带有AVPlayerItemsAVQueuePlayer的数组。 首先我设置AVQueuePlayer来播放数组项:

 func mediaPicker(mediaPicker: MPMediaPickerController!, didPickMediaItems mediaItemCollection: MPMediaItemCollection!) { mediaItems = mediaItemCollection.items for thisItem in mediaItems as [MPMediaItem] { var itemUrl = thisItem.valueForProperty(MPMediaItemPropertyAssetURL) as? NSURL var playerItem = AVPlayerItem(URL: itemUrl) mediaArray.append(playerItem) } updateMetadata() audioPlayer = AVQueuePlayer(items: mediaArray) self.dismissViewControllerAnimated(true, completion: nil) } 

但是,例如,当用户添加新项目或删除一个项目时,我会尝试更新播放器(就像我在第一时间设置它一样),但它给了我错误。 我想知道是否有任何方法,或任何解决方案。 这是用户删除歌曲的方式:

 func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) { if editingStyle == UITableViewCellEditingStyle.Delete{ mediaArray.removeAtIndex(indexPath.row) tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic) audioPlayer = AVQueuePlayer(items: mediaArray) //here gives the error } } 

我正在为此而自杀,所以,如果有人可以帮助我,我会很感激。

问题是,当您使用此行更新项目数组时,您正在创建一个新的播放器对象(在tableView中:commitEditingStyle:forRowAtIndexPath :),

 audioPlayer = AVQueuePlayer(items: mediaArray) 

当你这样做时,似乎玩家物品仍与原始玩家相关联。 您应该能够删除该行,以使其正常工作。 从mediaArray插入或删除项目应该足以做你想做的事情; 你不需要创建一个新玩家。

来自Apple文档 :

在添加项目之前:

canInsertItem(_:afterItem:)

返回一个布尔值,指示是否可以将给定的播放器项插入到播放器的队列中。

 func canInsertItem(_ item: AVPlayerItem!, afterItem afterItem: AVPlayerItem!) -> Bool 

添加项目:

 insertItem(_:afterItem:) 

在队列中的指定项目之后给予玩家项目的位置。

  func insertItem(_ item: AVPlayerItem!, afterItem afterItem: AVPlayerItem!) 

删除项目:

removeItem(_:)

从队列中删除给定的玩家项目。

func removeItem(_ item: AVPlayerItem!)

我解决这个问题的方法是在数组中保留对AVAsset对象的引用,然后mapmap[AVPlayerItem]AVQUeuePlayer init接受的类型)。

为了详细说明,我们需要制作一个可以暂停的录音机( github上的代码 ),所以我使用了AVQueuePlayer ,但遇到了与OP相同的问题,唯一干净的解决方案就是用新的方法重新创建这个播放器对象arrays。

Swift 4.1中的相关代码:

 class RecordViewController: UIViewController { var audioRecorder: AVAudioRecorder? var audioChunks = [AVURLAsset]() var queuePlayer: AVQueuePlayer? // irrelevant code omitted func stopRecorder() { self.audioRecorder?.stop() let assetURL = self.audioRecorder!.url self.audioRecorder = nil let asset = AVURLAsset(url: assetURL) self.audioChunks.append(asset) let assetKeys = ["playable"] let playerItems = self.audioChunks.map { AVPlayerItem(asset: $0, automaticallyLoadedAssetKeys: assetKeys) } self.queuePlayer = AVQueuePlayer(items: playerItems) self.queuePlayer?.actionAtItemEnd = .advance } func startPlayer() { self.queuePlayer?.play() } func stopPlayer() { self.queuePlayer?.pause() self.queuePlayer = nil } } 

(最后, AVAssetExportSession用于将音频块重新拼接在一起 ,因此存储AVAssetAVPlayerItem的内容最终会更有益。)