UICollectionView 在滚动时卡住
UICollectionView gets stuck while scrolling
我的 collectionView
单元格中有一些视频。我正在从 URL 中获取它们并使用 AVPlayer
.
进行播放
一切正常。但是,根据视频是否包含音频,需要显示 mute/unmute 图标。
为了检查视频是否包含音频,我使用了以下代码:
(self.player?.currentItem?.asset.tracks.filter({[=10=].mediaType == AVMediaType.audio}).count != 0)
我从:How to check if AVPlayer has Video or just Audio?
添加此代码后,当我滚动集合视图时,我的 collectionView 第一次卡住了。
我从单元格的 init 调用它。
尝试在后台线程上执行它,但我仍然遇到问题。
DispatchQueue.global(qos: .background).async {
let isAudioAvailable = (self.player?.currentItem?.asset.tracks.filter({[=11=].mediaType == AVMediaType.audio}).count != 0)
DispatchQueue.main.async {
self.audioIconButton.isHidden = !isAudioAvailable
self.player?.isMuted = isMuted
let image = isMuted ? #imageLiteral(resourceName: "Mute_Icon") : #imageLiteral(resourceName: "Unmute_Icon")
self.audioIconButton.setImage(image, for: .normal)
})
}
要从 URL 获取的代码:
func getAVPlayerFromUrl(view: UIView) -> AVPlayer? {
let size: CGSize = view.bounds.size.applying(CGAffineTransform(scaleX: UIScreen.main.scale, y: UIScreen.main.scale))
guard let url = URL(string: AppConfig.shared.appConfig.video_buckets.videoURL(for: self, size: size)) else { return nil }
let videoAsset = AVURLAsset(url: url)
videoAsset.loadValuesAsynchronously(forKeys: ["playable"])
let playerItem: AVPlayerItem = AVPlayerItem(asset: videoAsset)
return AVPlayer(playerItem: playerItem)
}
请让我知道这里出了什么问题。
或者有没有其他方法可以区分视频是否包含音频?
这里的想法是在加载 asset
时缓存计数,而不是加载 cell
因此获取逻辑将更改为类似于以下代码的内容
func getAVPlayerFromUrl(view: UIView, cellIndex: Int) -> AVPlayer? {
let size: CGSize = view.bounds.size.applying(CGAffineTransform(scaleX: UIScreen.main.scale, y: UIScreen.main.scale))
guard let url = URL(string: AppConfig.shared.appConfig.video_buckets.videoURL(for: self, size: size)) else { return nil }
let videoAsset = AVURLAsset(url: url)
videoAsset.loadValuesAsynchronously(forKeys: ["playable"]) {
// Here audioCount is the dict we are using to save the count and cellIndex is the index of the cell in collectionview
self.audioCount[cellIndex] = videoAsset.tracks.filter({[=10=].mediaType == AVMediaType.audio}).count
}
let playerItem: AVPlayerItem = AVPlayerItem(asset: videoAsset)
return AVPlayer(playerItem: playerItem)
}
最后像
一样使用它
let isAudioAvailable = (self.audioCount[index] != 0)
self.audioIconButton.isHidden = !isAudioAvailable
self.player?.isMuted = isMuted
let image = isMuted ? #imageLiteral(resourceName: "Mute_Icon") : #imageLiteral(resourceName: "Unmute_Icon")
self.audioIconButton.setImage(image, for: .normal)
我的 collectionView
单元格中有一些视频。我正在从 URL 中获取它们并使用 AVPlayer
.
一切正常。但是,根据视频是否包含音频,需要显示 mute/unmute 图标。
为了检查视频是否包含音频,我使用了以下代码:
(self.player?.currentItem?.asset.tracks.filter({[=10=].mediaType == AVMediaType.audio}).count != 0)
我从:How to check if AVPlayer has Video or just Audio?
添加此代码后,当我滚动集合视图时,我的 collectionView 第一次卡住了。
我从单元格的 init 调用它。 尝试在后台线程上执行它,但我仍然遇到问题。
DispatchQueue.global(qos: .background).async {
let isAudioAvailable = (self.player?.currentItem?.asset.tracks.filter({[=11=].mediaType == AVMediaType.audio}).count != 0)
DispatchQueue.main.async {
self.audioIconButton.isHidden = !isAudioAvailable
self.player?.isMuted = isMuted
let image = isMuted ? #imageLiteral(resourceName: "Mute_Icon") : #imageLiteral(resourceName: "Unmute_Icon")
self.audioIconButton.setImage(image, for: .normal)
})
}
要从 URL 获取的代码:
func getAVPlayerFromUrl(view: UIView) -> AVPlayer? {
let size: CGSize = view.bounds.size.applying(CGAffineTransform(scaleX: UIScreen.main.scale, y: UIScreen.main.scale))
guard let url = URL(string: AppConfig.shared.appConfig.video_buckets.videoURL(for: self, size: size)) else { return nil }
let videoAsset = AVURLAsset(url: url)
videoAsset.loadValuesAsynchronously(forKeys: ["playable"])
let playerItem: AVPlayerItem = AVPlayerItem(asset: videoAsset)
return AVPlayer(playerItem: playerItem)
}
请让我知道这里出了什么问题。 或者有没有其他方法可以区分视频是否包含音频?
这里的想法是在加载 asset
时缓存计数,而不是加载 cell
因此获取逻辑将更改为类似于以下代码的内容
func getAVPlayerFromUrl(view: UIView, cellIndex: Int) -> AVPlayer? {
let size: CGSize = view.bounds.size.applying(CGAffineTransform(scaleX: UIScreen.main.scale, y: UIScreen.main.scale))
guard let url = URL(string: AppConfig.shared.appConfig.video_buckets.videoURL(for: self, size: size)) else { return nil }
let videoAsset = AVURLAsset(url: url)
videoAsset.loadValuesAsynchronously(forKeys: ["playable"]) {
// Here audioCount is the dict we are using to save the count and cellIndex is the index of the cell in collectionview
self.audioCount[cellIndex] = videoAsset.tracks.filter({[=10=].mediaType == AVMediaType.audio}).count
}
let playerItem: AVPlayerItem = AVPlayerItem(asset: videoAsset)
return AVPlayer(playerItem: playerItem)
}
最后像
一样使用它let isAudioAvailable = (self.audioCount[index] != 0)
self.audioIconButton.isHidden = !isAudioAvailable
self.player?.isMuted = isMuted
let image = isMuted ? #imageLiteral(resourceName: "Mute_Icon") : #imageLiteral(resourceName: "Unmute_Icon")
self.audioIconButton.setImage(image, for: .normal)