我一直在尝试使用放置在 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-推荐答案 strong>
谢天谢地,你很幸运。 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 可能会更好,因为加载视频是用户启动操作的结果。
至于视频的实际缓存。我对 AVPlayer 或 AVPlayerItem 不是太熟悉,但据我了解,您可以提供更多元数据(即持续时间、轨道等) AVPlayer 在尝试在层中渲染视频之前,它运行得越快(参见这个相关的 StackOverflow Question )。
此外,您可能想要查看 iOS 10 中新引入的 API,您可以在表格 View 中预取单元格。如果您利用预取优化,您可能会在后台加载 AVPlayer 所需的所有内容,并且在请求单元格显示在 cellForRowAtIndexPath: 之前很久.
无论如何,希望您可以从那里开始并解决问题。一定要花时间阅读关于 AVKit 、GCD 和 UITableView 的文档(特别是新的预取 API)。
关于ios - 在 tableview 中平滑加载视频,我们在Stack Overflow上找到一个类似的问题:
https://stackoverflow.com/questions/43118501/
|