我知道这个问题已经遍布Stack Overflow了,但是大部分都是旧的,与我在这里要问的内容无关。
所以我有一个包含AVPlayerItems
和AVQueuePlayer
的数组。首先我设置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
}
}
我正在为此而自杀,所以,如果有人可以帮助我,我会很感激。
答案 0 :(得分:4)
问题在于,当您使用此行更新项目数组时,您正在创建新的播放器对象(在tableView中:commitEditingStyle:forRowAtIndexPath :),
audioPlayer = AVQueuePlayer(items: mediaArray)
当您执行此操作时,似乎玩家项目仍与原始玩家相关联。您应该能够删除该行,以使其正常工作。从mediaArray插入或删除项目应该足以做你想做的事情;你不需要创建一个新玩家。
答案 1 :(得分:2)
我解决这个问题的方法是,我在数组中保留对AVAsset
个对象的引用,然后map
将其转换为[AVPlayerItem]
(AVQUeuePlayer
init的类型接受)。
详细说明,我们需要制作一个可以暂停的录音机(code on github),所以我使用了AVQueuePlayer
,但遇到了与OP相同的问题,也是唯一一个干净的解决方案是用新数组重新创建这个玩家对象。
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
is used to stitch the chunks of audio back together,因此最后存储AVAsset
AVPlayerItem
个parted
的内容更为有利。)
答案 2 :(得分:1)
在添加项目之前:
canInsertItem(_:afterItem:)
返回指示的布尔值 是否可以将给定的玩家项目插入到玩家的队列中。
func canInsertItem(_ item: AVPlayerItem!, afterItem afterItem: AVPlayerItem!) -> Bool
添加项目:
insertItem(_:afterItem:)
在队列中指定的项目之后放置给定的玩家项目。
func insertItem(_ item: AVPlayerItem!, afterItem afterItem: AVPlayerItem!)
删除项目:
removeItem(_:)
从队列中删除给定的玩家项目。
func removeItem(_ item: AVPlayerItem!)
答案 3 :(得分:0)
需要检查播放器项目是否可以插入播放器队列中。然后根据以下条件添加,删除或替换播放器项目:
if player.canInsert(playerItem, after: nil) == true {
player = AVQueuePlayer(playerItem: playerItem)
} else {
player.remove(self.playerItem)
player.replaceCurrentItem(with: playerItem)
}
答案 4 :(得分:0)
使用此代码为我解决了问题:
player?.pause() let playerItem = AVPlayerItem(asset: myAsset) player = nil player = AVPlayer() player?.replaceCurrentItem(with: playerItem)
代替:
player?.pause() player = nil player = AVPlayer() player?.replaceCurrentItem(with: availablePlayerItem) // availablePlayerItem is a playerItem which has been created before and played once with this AVPlayer
注意: 在这两个代码中,“玩家”是我班上的一个全局变量,它是:
var player:AVPlayer? =零
答案 5 :(得分:0)
我最初在单元格内初始化了一个AVPlayerItem并将其添加到AVPlayer(也在单元格内)。后来我提出了一个新的vc,并将同一单元格的AVPlayerItem传递到新vc内的另一个AVPlayer上,并导致崩溃。要修复它,我只是使用.copy() as? AVPlayerItem
复制了playerItem。副本为新副本提供了与原始副本不同的内存地址。
单元格:
var cellPlayer: AVPlayer?
var cellsPlayerItem: AVPlayerItem?
cellsPlayerItem = AVPlayerItem(asset: AVAsset(url: url)) // cellsPlayerItem's memory address 0x1111111
cellPlayer = AVPlayer(playerItem: cellsPlayerItem!)
展示的vc:
var vcPlayer: AVPlayer?
let playerItemCopy = cellsPlayerItem.copy() as? AVPlayerItem // playerItemCopy's memory address 0x2222222
let vcPlayer = AVPlayer(playerItem: playerItemCopy)