[Swift] TikTok-Like Video Display Cells
-
Trouble with initialising player variable. I have tried on init methods throws error. Trouble with are multiple instances of Video, When I put the app on background and foreground again videos Starts playing Simultaneously (From current cell and from top and bottom to the current cell).
On DidEndDisplay, I have tried - Passing nil url and removing the playerView, Passing nil url doesn’t change the instance and ”var player = nil “ isn’t allowed -> “throws Player cannot be assigned nil”.
If I remove the player.view on didEndDisplay and add it as a subview on willDisplay, The Outcome is that the player.view is not added as a subview so quick and only audio is heard. i.e Breaking functionalityQuestion
1. Where do I initialise the player.
2. Which functions of Collection View should I use to de-initalise it, and How?Following is the code
My Custom CollectionCellimport UIKit import Player class HomeCell: UICollectionViewCell { let player = Player() @IBOutlet weak var playerView: UIView! // MARK: - OtherOutlet Variables func removeVideo() { self.player.asset = nil self.player.url = nil } func playerInitialization() { print("playerInitialization") self.player.playerDelegate = self self.player.playbackDelegate = self self.playerView.addSubview(self.player.view) player.view.translatesAutoresizingMaskIntoConstraints = false player.view.topAnchor.constraint(equalTo: playerView.topAnchor).isActive = true player.view.leadingAnchor.constraint(equalTo: playerView.leadingAnchor).isActive = true player.view.trailingAnchor.constraint(equalTo: playerView.trailingAnchor).isActive = true player.view.bottomAnchor.constraint(equalTo: playerView.bottomAnchor).isActive = true self.player.fillMode = .resizeAspectFill self.player.playbackLoops = false let tapGestureRecognizer: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleTapGestureRecognizer(_:))) self.player.view.addGestureRecognizer(tapGestureRecognizer) tapGestureRecognizer.numberOfTapsRequired = 1 } override func prepareForReuse() { super.prepareForReuse() } func populate(videoUrl:String){ print(videoUrl) self.player.url = URL(string:videoUrl) } } extension HomeCell { @objc func handleTapGestureRecognizer(_ gestureRecognizer: UITapGestureRecognizer) { switch self.player.playbackState { case .stopped: self.player.playFromBeginning() break case .paused: self.player.playFromCurrentTime() break case .playing: self.player.pause() break case .failed: self.player.pause() break } } } // MARK: - PlayerDelegate extension HomeCell: PlayerDelegate { func playerReady(_ player: Player) { // print("\(#function) ready") } func playerPlaybackStateDidChange(_ player: Player) { // print("\(#function) \(player.playbackState.description)") } func playerBufferingStateDidChange(_ player: Player) { } func playerBufferTimeDidChange(_ bufferTime: Double) { } func player(_ player: Player, didFailWithError error: Error?) { // print("\(#function) error.description") } } // MARK: - PlayerPlaybackDelegate extension HomeCell: PlayerPlaybackDelegate { func playerCurrentTimeDidChange(_ player: Player) { } func playerPlaybackWillStartFromBeginning(_ player: Player) { } func playerPlaybackDidEnd(_ player: Player) { } func playerPlaybackWillLoop(_ player: Player) { } func playerPlaybackDidLoop(_ player: Player) { } }
MainViewController
import UIKit import Alamofire class HomeCollectionVC: UIViewController,UICollectionViewDelegateFlowLayout { var talents = [Talent]() @IBOutlet weak var mainView: UIView! @IBOutlet var collectionView: UICollectionView! override func viewDidLoad() { super.viewDidLoad() collectionView.delegate = self collectionView.dataSource = self print("Collection View”) TalentService.getCategoryTalents(category:"foryou") { (success, response, error) in if success { print(" getForyouTalents on ViewDidLoad") guard let talents = response else { return } self.collectionView.reloadData() print("RELOAD") self.talents = talents } else { let error = error print("caught at collection viewcontroller foryouButton \(error ?? "nil" as! Error)") } } }
}
extension HomeCollectionVC: UICollectionViewDataSource {func numberOfSections(in collectionView: UICollectionView) -> Int { return 4 } func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return talents.count } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "HomeCell", for: indexPath) as? HomeCell else { return UICollectionViewCell() } cell.playerInitialization() let videoUrl = talents[indexPath.item].videoUrl cell.populate(videoUrl: videoUrl) return cell } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { return CGSize(width: collectionView.frame.width, height: collectionView.frame.height) } func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) { print("willDisplay \(indexPath.row)") } func collectionView(_ collectionView: UICollectionView, didEndDisplaying cell: UICollectionViewCell, forItemAt indexPath: IndexPath) { (cell as? HomeCell)?.player.stop() (cell as? HomeCell)?.removeVideo() print("endDisplay \(indexPath.row)") } func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { collectionView.visibleCells.forEach { cell in (cell as? HomeCell)?.player.playFromBeginning() print("scrollViewDidEndDecelerating") } }
Additionally- piemonte/Player this library that I am using is probably making me run into these problems.
IJKPlayer will could me a lot of trouble. So if you knowany article to setup and use IJK Player with swift please do share as I tried couldn’t get through :)
-