AVPlayer / AVPlayerLayer not appearing in subview

2019-06-25 04:40发布

问题:

I'm trying to display a video inside of a subview which contains the video and some text. I used the recommended UIView subclass from Apple to create a UIView to contain my AVPlayer:

import Foundation
import AVFoundation

class JSAVPlayerView : UIView {
    var player:AVPlayer? {
        get {
            return (self.layer as! AVPlayerLayer).player
        }
        set(newPlayer) {
            (self.layer as! AVPlayerLayer).player = newPlayer
        }
    }

    override class func layerClass() -> AnyClass {
        return AVPlayerLayer.self
    }
}

I used JSAVPlayerView as a subview in a UICollectionViewCell as shown below, but I only ever see the background of the JSAVPlayerView.

class JSOnBoardingTutorialPageView : UICollectionViewCell {
    // MARK: member variables
    private var tutorialVideoPlayer:AVPlayer!
    private var videoPlayerView:JSAVPlayerView = JSAVPlayerView()
    private var tutorialLabel:UILabel = UILabel()
    var tutorialText:String = "" {
        didSet {
            tutorialLabel.text = tutorialText
        }
    }

    // MARK: auto layout variables
    private var metrics:[String:CGFloat] = [
        "marginTop" : 30,
        "marginLeft" : 30,
        "marginRight" : 30,
        "marginBottom" : 30,
        "textHeight" : 100,
    ]
    private var autolayoutConstraints:[NSLayoutConstraint] = [NSLayoutConstraint]()







    // MARK: constructors
    override init(frame: CGRect) {
        super.init(frame: frame)

        self.backgroundColor = UIColor.jsBrandBlack()

        self.setupSubviews()
    }

    init() {
        super.init(frame: CGRect.zero)

        self.backgroundColor = UIColor.jsBrandBlack()

        self.setupSubviews()
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }







    // MARK: subview setup
    func setupSubviews() {
        self.setupTutorialVideoView()
        self.setupTutorialLabel()

        self.setupConstraints()

        self.addConstraints(self.autolayoutConstraints)
    }

    func setupTutorialVideoView() {
        self.videoPlayerView.translatesAutoresizingMaskIntoConstraints = false

        self.videoPlayerView.backgroundColor = UIColor.blueColor()

        if let player = self.tutorialVideoPlayer {
            self.videoPlayerView.player = player
        }

        self.addSubview(self.videoPlayerView)
    }

    func setupTutorialLabel() {
        self.tutorialLabel.translatesAutoresizingMaskIntoConstraints = false
        self.tutorialLabel.textColor = UIColor.jsLightGray()
        self.tutorialLabel.font = UIFont.jsH3WithWeight(.Normal)
        self.tutorialLabel.numberOfLines = 0
        self.tutorialLabel.textAlignment = .Center

        self.addSubview(self.tutorialLabel)
    }

    func setupConstraints() {
        let views:[String:AnyObject] = [
            "video" : self.videoPlayerView,
            "text" : self.tutorialLabel
        ]

        self.autolayoutConstraints.appendContentsOf(
            NSLayoutConstraint.constraintsWithVisualFormat(
                "V:|-marginTop-[video]-marginBottom-[text(text@750)]-|",
                options: .AlignAllCenterX,
                metrics: self.metrics,
                views: views
            )
        )

        self.autolayoutConstraints.appendContentsOf(
            NSLayoutConstraint.constraintsWithVisualFormat(
                "H:|-marginLeft-[video]-marginRight-|",
                options: NSLayoutFormatOptions(),
                metrics: self.metrics,
                views: views
            )
        )

        self.autolayoutConstraints.appendContentsOf(
            NSLayoutConstraint.constraintsWithVisualFormat(
                "H:|-marginLeft-[text]-marginRight-|",
                options: NSLayoutFormatOptions(),
                metrics: self.metrics,
                views: views
            )
        )
    }







    // MARK: video setup
    func setVideo(url:NSURL) {
        self.tutorialVideoPlayer = AVPlayer(URL: url)

        self.videoPlayerView.player = self.tutorialVideoPlayer

        let playerLayer:AVPlayerLayer = self.videoPlayerView.layer as! AVPlayerLayer
        playerLayer.frame = self.videoPlayerView.frame
        playerLayer.videoGravity = AVLayerVideoGravityResizeAspectFill
    }

    func playVideo() {
        let playerLayer = self.videoPlayerView.layer as! AVPlayerLayer

        if playerLayer.readyForDisplay {
            self.tutorialVideoPlayer.play()
        } else {
            print("Player not ready to play")
        }
    }

    func pauseVideo() {
        self.tutorialVideoPlayer.pause()
    }







    // MARK: layout hack
    override func layoutSubviews() {
        super.layoutSubviews()

        self.tutorialLabel.preferredMaxLayoutWidth = CGRectGetWidth(self.tutorialLabel.bounds)

        super.layoutSubviews()
    }
}

Inside my view controller, I set the UICollectionViewCell (and the URL of the video I'm trying to display) like this:

let cell:JSOnBoardingTutorialPageView = collectionView.dequeueReusableCellWithReuseIdentifier(self.CollectionViewCellReuseIdentifer, forIndexPath: indexPath) as! JSOnBoardingTutorialPageView

if let index = JSOnBoardingTutorialPage(rawValue: indexPath.row) {
    cell.setVideo((self.pageData[index]?.video)!)
    print(String(format: "video url: %@", (self.pageData[index]?.video)!))

    cell.tutorialText = (self.pageData[index]?.text)!
    cell.playVideo()
}

return cell

How do I get my video to display in its container JSAVPlayerView?

回答1:

I think the problem is that you never call the constructor of AVPlayer (as far as I can see from the code you provided). There is a function func setVideo(url: NSURL), but you do not call this function.