2

I read the following article:

I am loading videos in AVPlayer in collection view but it repeats some cells data

My attempts:

controller:

    let vidos = ["v1","v2","v3"]

    let collection : UICollectionView = {
        let layout  = UICollectionViewFlowLayout.init()
        layout.scrollDirection = .vertical
        let colle = UICollectionView.init(frame: .zero, collectionViewLayout: layout)
        colle.translatesAutoresizingMaskIntoConstraints = false
        colle.isPagingEnabled = true
        colle.showsVerticalScrollIndicator = false
        return colle
    }()

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
        setUpView()
    }
    func setUpView(){
        collection.delegate = self;
        collection.dataSource = self;
        collection.register(vieosCell.self, forCellWithReuseIdentifier: collId)
        collection.backgroundColor = UIColor.darkGray
        view.addSubview(collection);
        
        collection.snp.makeConstraints { (make) in
            make.top.left.equalTo(view)
            make.bottom.right.equalTo(view)
        }
        
    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return vidos.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: collId, for: indexPath) as! vieosCell
//        cell.imagSrc = images[indexPath.row]
//        print("111",indexPath.row)
        cell.vido_url = vidos[indexPath.row]
        return cell
    }
    
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return CGSize(width: view.frame.width, height:view.frame.height )
    }
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
        return 0
    }

cell:

    var vido_url : String?{
        didSet{
            guard let src = vido_url else{
                return
            }
            loadVideo(src)
        }
    }
    
    var player : AVPlayer?
    var plyaerLayer : AVPlayerLayer?
    
    func loadVideo(_ url:String){
        
        guard let path = Bundle.main.path(forResource: url, ofType: "mp4") else {
            return
        }
        player = AVPlayer(url: URL(fileURLWithPath:path))
        plyaerLayer = AVPlayerLayer(player: player)
        plyaerLayer?.frame = contentView.bounds;
        plyaerLayer?.videoGravity = .resizeAspectFill
        contentView.layer.addSublayer(plyaerLayer!)
        player?.play()
    }

    override func prepareForReuse() {
        super.prepareForReuse()
        plyaerLayer?.removeFromSuperlayer()
        player?.pause()

    }

The cell takes up the entire screen, so when I want to switch videos up and down, I want to pause the previous video.

But now when you switch, it continues to play the previous video

Console appears:

2020-08-26 10:11:51.032419+0800 Demo[3253:76257] [plugin] AddInstanceForFactory: No factory registered for id <CFUUID 0x600002234be0> F8BB1C28-BAE8-11D6-9C31-00039315CD46

Thank you very much for your help

  • It's hard to tell base on only the cell code. Please included how you code your delegate/datasource of the collection view. – MatthewLuiHK Aug 26 '20 at 02:47
  • @MatthewLuiHK Has been added – BaiClassmate Xiao Aug 26 '20 at 02:50
  • Seems quite decent, the problem seems like something happen when you do the clean up. Perhaps you can try to print if the playerLayer can be successfully remove after your call? Seems it's not been removed. Sometime apple's framework required some specific clean up flow for example stop the player then remove etc. BTW, why brother remove and add a new layer everytime ... – MatthewLuiHK Aug 26 '20 at 02:57
  • @MatthewLuiHK How do I manage it properly? Because it's reusable – BaiClassmate Xiao Aug 26 '20 at 03:13
  • 1) You should print and see if the layer is removed first, this would lead you to find the actual problem and answer. 2) think about the objective why you want the layer be remove and add, is it directly required by your business goal? If what you want is pause the old video and play the new video, what's the minimal required step? – MatthewLuiHK Aug 26 '20 at 03:16
  • @MatthewLuiHK It has some cells that have not been deleted, that have been reused, And I don't know how to deal with that.. – BaiClassmate Xiao Aug 26 '20 at 03:19
  • https://developer.apple.com/documentation/avfoundation/avplayer – MatthewLuiHK Aug 26 '20 at 03:21
  • @MatthewLuiHK 1).It is cached, it has not been deleted, and the prepareForReuse is invalid. 2). Get the old cell's and let it pause – BaiClassmate Xiao Aug 26 '20 at 03:44
  • The information is not enough. Could you show the code of the initialization of tableview? Especially the register for cell. – Lynx Aug 26 '20 at 03:47
  • @Lynx Has been added,Can you see it? – BaiClassmate Xiao Aug 26 '20 at 03:50
  • by "1).It is cached, it has not been deleted, and the prepareForReuse is invalid." what invalid? is it never been executed? Have you print the cell layer's sublayer and see if your AVPlayerLayer is actually been removed yet? If it's not even executed, then you know what's the problem. If the layer is not removed, then you know what's the problem. If both work fine, then you know what's not the problem – MatthewLuiHK Aug 26 '20 at 03:55

0 Answers0