[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 functionality

    Question
    
 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 CollectionCell

    import 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 :)


  • Notification Spam Recipient