事情是这样的: 我正在开发一个包含新闻提要(非常类似于 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() }
}
非常感谢