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
?
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 functionfunc setVideo(url: NSURL)
, but you do not call this function.