【问题标题】:UICollectionView gets stuck while scrollingUICollectionView 在滚动时卡住
【发布时间】:2019-07-19 05:37:21
【问题描述】:

我的collectionView 单元格中有一些视频。我从 URL 中获取它们并使用 AVPlayer 播放它。

一切正常。但是,根据视频是否包含音频,需要显示静音/取消静音图标。

为了检查视频是否包含音频,我使用了以下代码:

(self.player?.currentItem?.asset.tracks.filter({$0.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({$0.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)
}

请让我知道这里出了什么问题。 或者有没有其他方法来区分视频是否包含音频?

【问题讨论】:

  • 您可以检查您的数据源中的这些数据,而不是检查播放器的当前项目吗?
  • @CerlinBoss 你能告诉我怎么做吗?仅供参考,我从 URL 获取此视频并在 AVPlayer 中播放。
  • 能否在问题中添加获取逻辑?
  • 尝试将 completionHandler 添加到 loadValuesAsynchronously 并获取计数并缓存它。稍后在 init 中,检查缓存的值
  • 谢谢! @CerlinBoss 我请求您将其添加为可能对其他人有所帮助的答案,

标签: ios swift uicollectionview avplayer


【解决方案1】:

这里的想法是缓存加载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({$0.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)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-20
    • 1970-01-01
    • 2016-06-04
    • 1970-01-01
    • 2014-06-29
    相关资源
    最近更新 更多