如何观察 AVPlayerItem 准备播放以停止 ActivityIndi​​cator 的那一刻?

时间:2021-06-15 15:39:04

标签: ios swift avplayer key-value-observing collectionview

事情是这样的: 我正在开发一个包含新闻提要(非常类似于 Instagram 的提要)的应用,我可以在其中显示图像和视频。

我配置了一个 CollectionView,其中包含不同的单元格(供稿中的每个项目一个),并且该单元格有两种类型:VideoCell 和 ImageCell。

我遇到的问题是 Video 单元格包含一个 AVPlayer,其中包含一个 AVPlayerItem,它使用来自给定 URL 的视频,并且这些视频在开始播放之前会以黑色显示一段时间。< /p>

我想要的是从显示单元格的那一刻到视频准备好开始播放的那一刻显示一个活动指示器。

我听说观察者可能很有用,但我不知道如何实现 KVO,因为我是 iOS 开发的新手。 这是我的课:

// 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() }
}

非常感谢

0 个答案:

没有答案