将tableViewCell保存在数组中,将UITableViewCell缓存在数组中

Save tableViewCell in an array, Cache UITableViewCell in an array

我正在开发一个 tableView,其中每个单元格都由 AVPlayer 组成,高度为 view.frame.size.height,并且还启用了分页。所以基本上它的工作方式类似于 tiktok 应用程序提要。我遇到的问题是,我必须在调用 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

这听起来更像是集合视图的工作。一旦收到数据,您应该能够通过预取和填充要显示的单元格来实现您想要的平滑加载。

https://developer.apple.com/documentation/uikit/uicollectionviewdatasourceprefetching/prefetching_collection_view_data

Prefetching Collection View Data

Load data for collection view cells before they are displayed.

A collection view displays an ordered collection of cells in customizable layouts. The UICollectionViewDataSourcePrefetching protocol helps provide a smoother user experience by prefetching the data necessary for upcoming collection view cells. When you enable prefetching, the collection view requests the data before it needs to display the cell. When it’s time to display the cell, the data is already locally cached.

The image below shows cells outside the bounds of the collection view that have been prefetched.

如果这不能满足您的需求,请post您的代码。

更新:

我花了很多时间试图用 tableView 解决这个问题,但未能如愿。我最终制作了一个带有滚动视图的自定义表格视图,它具有问题中提出的类似实现。所以用 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)
}