Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UITableView didEndDisplaying not called when video is playing

I already tried to find here a similar question without success.

I have a UITableView with various kinds of contents and cells. In particular, it can show a custom UITableViewCell with a WKWebView. Sometimes this web view has an autoplay video that starts when I configure the cell on willDisplayCell. Because of this autoplay feature, when I scroll up/down, the cell does not call the delegate method didEndDisplayingCell and the video stays active in the background. The user needs to close the viewController or the whole App.


I tried to save on a list all the dequeued cells with web view and on scrollViewDidEndDecelerating manually set the content of the saved cell's web view to HTML "" using:

cell.webView?.loadHTMLString("", baseURL: nil)

In this way, the web view properly stops playing the video in the background but the problem is that even using this approach the cell is not enqueued and the didEndDisplayingCell: is not called, so when I scroll to that cell again, I can't redo correct configuration to reload the web view.

Do you have some tips or tricks?

like image 511
Alessio Zap Boerio Avatar asked Oct 29 '22 20:10

Alessio Zap Boerio


1 Answers

I solved with a workaround. Basically the cell isn't recycled for some strange reason, regarding how the webView handles video in that case. So I save all those cells as instance property in a Set and in scrollViewDidScroll(_:) I check if the cell is still visible. If it's not visible, I manually remove the webView from its superview.

var advTableViewCells = Set<AdvertisingTableViewCell>() // here I save the cell retrieved in `tableView(_:cellForRowAt:)` 

func scrollViewDidScroll(_ scrollView: UIScrollView) {  
    var cellsToRemove = Set<AdvertisingTableViewCell>() // save the cell to remove in a temporary set, to avoid removing element in a forEach
    advTableViewCells.forEach { cell in
        if !tableView.visibleCells.contains(cell) {
            cell.webView?.stopLoading()
            cell.webView?.removeFromSuperview()
            cell.webView = nil
            cellsToRemove.insert(cell)
        }
    }
    cellsToRemove.forEach { cell in
        self.advTableViewCells.remove(cell)
    }
}
like image 72
Rico Crescenzio Avatar answered Nov 08 '22 12:11

Rico Crescenzio