0

Here is the thing: I'm developing an app which consists in a feed on news (very similar to Instagram's feed), where I can display images and videos.

I configured a CollectionView which contains different cells (one for each item on the feed) and this cells have two types: VideoCell and ImageCell.

The Trouble I'm having is that Video cells contain an AVPlayer and inside of it, an AVPlayerItem which consumes a video from a given URL, and this videos are being displayed in black for a while until they start the playback.

What I want is to display an activityIndicator from the moment the cell is displayed until the moment the video is ready to start the playback.

I have heard that an observer could be useful but I don't know how to implement KVO since I'm somehow newbie on iOS development. This is my class:

// MARK: - VideoItemCollectionViewCell
final class VideoItemCollectionViewCell: MDCCardCollectionCell {
    static let reuseIdentifier = "videoItem"
    weak var delegate: NewsItemCellDelegate?

    lazy var activityIndicator: UIActivityIndicatorView = {
        let activityIndicator = UIActivityIndicatorView(style: UIActivityIndicatorView.Style.large)
        activityIndicator.color = .vixonicColor
        return activityIndicator
    }()
    
    private lazy var avPlayer: AVPlayer = AVPlayer(playerItem: nil)
    
    private lazy var avPlayerLayer: AVPlayerLayer = {
        let playerLayer = AVPlayerLayer(player: self.avPlayer)
        playerLayer.videoGravity = .resize
        return playerLayer
    }()
    
    var videoPlayerItem: AVPlayerItem? = nil {
        didSet {
            avPlayer.replaceCurrentItem(with: videoPlayerItem)
        }
    }

    private var isSound = true {
        didSet {
            avPlayer.isMuted = !isSound
            if isSound {
                audioImageView.image = UIImage(named: "audio_enabled_icon")
            } else {
                audioImageView.image = UIImage(named: "audio_disabled_icon")
            }
        }
    }

    var dataSource: News? {
        didSet {
            guard let dataSource = dataSource else { return }

            let dateDataSource = dataSource.creationDate ?? .empty

            let dateAsDate = dateDataSource.toDate(with: "yyyy-MM-dd HH:mm:ss Z")
            let dateAsString = dateAsDate?.toString(with: "dd MMMM")
            let timeAsString = dateAsDate?.toString(with: "HH:mm")
            let resourceId = dataSource.resourceId

            likeButton.imageView?.contentMode = .scaleAspectFit

            setLikeButton(using: resourceId)

            if !dataSource.buttons.indices.contains(0) {
                leftButton.isHidden = true
            } else {
                leftButton.setTitle(dataSource.buttons[0].text, for: .normal)
            }

            if !dataSource.buttons.indices.contains(1) {
                rightButton.isHidden = true
            } else {
                rightButton.setTitle(dataSource.buttons[1].text, for: .normal)
            }

            startActivityIndicator()
            
            dateLabel.text = "\(dateAsString ?? "") a las \(timeAsString ?? "")"
            likeCounterLabel.text = String(dataSource.interactions?.likeCount ?? 0)

            let urlString = dataSource.mediaUrl ?? ""
            if let url = URL(string: urlString) {
                videoPlayerItem = AVPlayerItem(url: url)
                setupMoviePlayer()
            }
        }
    }
}

// MARK: - Video Utils
extension VideoItemCollectionViewCell {
    func setupMoviePlayer() {
        
        avPlayer.volume = 1
        avPlayer.actionAtItemEnd = .none

        avPlayerLayer.frame = CGRect(x: 0, y: 0, width: self.frame.size.width, height: videoView.frame.size.height)

        self.backgroundColor = .none

        videoView.layer.addSublayer(avPlayerLayer)

        NotificationCenter.default.addObserver(self,
                                               selector: #selector(playerItemDidReachEnd(notification:)),
                                               name: .AVPlayerItemDidPlayToEndTime,
                                               object: avPlayer.currentItem)

        isSound = false
        stopActivityIndicator()
        avPlayer.play()
    }

    func stopPlayback() { avPlayer.pause() }
    func startPlayback() { avPlayer.play() }
    func toggleVideoAudio() { isSound.toggle() }
}

Thank you very much

0 Answers0