我正在开发一个tableView,其中每个单元格由AVPlayer组成,高度为view.frame.size.height,并且还启用了分页功能,所以本质上它的工作原理类似于tiktok的应用feed.我遇到的问题是,当调用cellForRow时,我必须在prepareForReuse中销毁AVPlayer以显示新的视频,否则如果我不销毁它,用户快速滚动,旧的视频就会出现在一个单元格中。我遇到的问题是,当调用cellForRow时,我必须在prepareForReuse中销毁AVPlayer以显示新的视频,否则如果我不销毁它,用户快速滚动,旧的视频就会出现一秒钟,如果我每次使用前都销毁播放器,那么AVPlayer需要一秒钟的时间来加载,并且在两者之间显示黑屏。它的工作,但结果是不优雅。
所以有什么方法可以让我预加载单元格并将它们保存在一个数组中。像一个数组,它将由三个独立的单元格组成,当用户滚动时,我们可以改变它们的值。
比如说
[] represents cell on screen
0 [1] 2
array[1] would always be the cell on screen
array[0] previous
array[2] next
if user scroll down then
array[0] = array[1]
array[1] = array[2]
array[2] = create next one (proactively)
if user scroll up then
let array1 = array[1]
array[1] = array[0]
array[0] = array1
array[2] = create new one
这听起来更像是一个集合视图的工作。你应该可以通过预取和填充单元格来实现你想要的平滑加载,一旦收到数据就会显示。
预取收集查看数据
在显示集合视图单元格之前为它们加载数据。
收集视图以可定制的布局显示有序的单元格集合。UICollectionViewDataSourcePrefetching协议通过预取即将到来的集合视图单元格所需的数据,帮助提供更流畅的用户体验。当您启用预取时,集合视图会在需要显示单元格之前请求数据。当需要显示单元格时,数据已经被本地缓存。
下图显示的是在集合视图范围外已被预取的单元格。
如果这不能满足你的要求,请把你的代码贴出来。
更新了。
我花了很多时间试图用tableView解决这个问题,但无法做到。最后我做了一个自定义的tableview和scrollview,其中有类似问题中问到的实现。所以,用scrollview来预加载单元格是可行的。下面提供的代码仅供参考
func scrollViewDidScroll(_ scrollView: UIScrollView) {
//Condition for first cell
if currentIndex == 0 && (scrollView.contentOffset.y > view.frame.minY) {
//pageIndex will only be one if the user completly scrolls the page, if he scroll half a returns it will remain 0
if pageIndex == 1 {
//so if the user completely scroll to page 1 the change the previous index to 0
//new current index will be 1
//call scrollForward which will prepare the cell for index 2
previousIndex = currentIndex
currentIndex = Int(pageIndex)
if shouldCallScrollMethods {
scrollForward()
}
guard let currentCell = getCellOnScreen() else { return }
currentCell.refreshBottomBarView()
}
//Condition for rest of the cells
} else {
//this condition checks if the user completly scroll to new page or just drag the scrollview a bit gets to old position
if (pageIndex != currentIndex) {
//Update the previous and current to new values
previousIndex = currentIndex
currentIndex = Int(pageIndex)
//Checks if the user is scroll down the calls scrollForwad else scrollBackward
if shouldCallScrollMethods {
if currentIndex > previousIndex {
scrollForward()
} else {
scrollBackward()
}
}
guard let currentCell = getCellOnScreen() else { return }
currentCell.refreshBottomBarView()
}
}
}
private func scrollForward() {
//print("scrollForward")
addCell(at: currentIndex + 1, url: getPlayerItem(index: currentIndex + 1))
removeCell(at: currentIndex - 2)
}
private func scrollBackward() {
//Condition to check if the element is not at 0
//print("scrollBackward")
addCell(at: currentIndex - 1, url: getPlayerItem(index: currentIndex - 1))
removeCell(at: currentIndex + 2)
}