OGeek|极客世界-中国程序员成长平台

标题: ios - 在 tableview 中平滑加载视频 [打印本页]

作者: 菜鸟教程小白    时间: 2022-12-11 19:23
标题: ios - 在 tableview 中平滑加载视频

我一直在尝试使用放置在 TableView 单元中的 AVPlayer 将一些视频添加到我的 tableView 中。

但在加载视频时 UI 会卡住。

这是我在 indexpath 中的 cellforRow。

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCel {


    var tableCell : UITableViewCell? = nil

    if (tableCell == nil){

        tableCell = tableView.dequeueReusableCell(withIdentifier: "cell")
    }

    let view = tableCell?.viewWithTag(9999)
    tableCell?.tag = indexPath.row


    DispatchQueue.main.async {
         if (tableCell?.tag == indexPath.row){
                let player = self.cache.object(forKey: indexPath.row as AnyObject) as! AVPlayer
                let playerLayer = AVPlayerLayer(player: player)
                playerLayer.frame = (view?.bounds)!
                view?.layer.addSublayer(playerLayer)
                player.play()

            }

//            tableView.reloadData()
    }

 return tableCell!
}

这就是我将视频添加到缓存的方式。

    for i in 0...10{

        var videoURL : URL? = nil

        if (i%2 == 0){

            videoURL = URL(string: "https://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4")
        }else{

            videoURL = URL(string: "http://techslides.com/demos/sample-videos/small.mp4")

        }
        let player = AVPlayer(url: videoURL!)

        arr?.append(player)

        self.cache.setObject(player, forKey: i as AnyObject)
        print("count = \(arr?.count)")
    }

解决此问题的最佳方法是什么?



Best Answer-推荐答案


谢天谢地,你很幸运。 iOS 仅针对这些类型的问题进行了优化。 Apple 工程师竭尽全力提供 API 来帮助您实现流畅的滚动同时加载您的内容。

Note: Solving this issue requires offloading tasks to different threads on the CPU. It can get complicated, and there's a lot to learn about it. I strongly recommend you read Apple's documentation.

首先,要知道cellForRowAtIndexPath: 方法应该一般在主线程上调用你的数据源。这意味着您必须调用 DispatchQueue.main.async 在这种情况下不合适。

相反,您需要将 AVPlayer 缓存卸载到单独的后台线程,然后返回主线程以更新单元格的层内容。此外,您不应该在 cellForRowAtIndexPath: 中这样做。您可能需要子类化一个 UITableViewCell 并在其中编写自己的加载序列 - 这样,您可以快速 init 自定义单元格,将其交还给 cellForRowAtIndexPath:(然后可以愉快地继续),并继续从单元子类中加载和更新。

要在后台线程中设置您的 AVPlayer,请执行以下操作:

DispatchQueue.global(qos: .background).async {
    // Background thread
    // Do your AVPlayer work here

    // When you need to update the UI, switch back out to the main thread
    DispatchQueue.main.async {
        // Main thread
        // Do your UI updates here
    }
}

您可能希望查看在创建后台线程时传入的服务质量值。对于这种特定情况,userInitiated QOS 可能会更好,因为加载视频是用户启动操作的结果。

至于视频的实际缓存。我对 AVPlayerAVPlayerItem 不是熟悉,但据我了解,您可以提供更多元数据(即持续时间、轨道等) AVPlayer 在尝试在层中渲染视频之前,它运行得越快(参见这个相关的 StackOverflow Question )。

此外,您可能想要查看 iOS 10 中新引入的 API,您可以在表格 View 中预取单元格。如果您利用预取优化,您可能会在后台加载 AVPlayer 所需的所有内容,并且在请求单元格显示在 cellForRowAtIndexPath: 之前很久.

无论如何,希望您可以从那里开始并解决问题。一定要花时间阅读关于 AVKitGCDUITableView 的文档(特别是新的预取 API)。

关于ios - 在 tableview 中平滑加载视频,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43118501/






欢迎光临 OGeek|极客世界-中国程序员成长平台 (http://ogeek.cn/) Powered by Discuz! X3.4