Reputation: 838
I want to fetch a video from a url and play it inside a view on tap of a button.
I have a moviePlayer which plays a video from a URL. Everything looks good but when I click on Back or Next button (i.e. change the viewController) the video continues to play (as I am still able to hear the audio on the new screen.
So I thought of add moviePlayer.Stop() on viewDidDismiss. It works good on first view change, but when I come back to the moviePlayer view and click next I find a nil error at moviePlayer.Stop() (as the movie is already stopped). Can someone help me understand how to do this?
import UIKit import MediaPlayer
class InformationViewController: UIViewController {
@IBOutlet var thumbnailImage: UIImageView!
@IBOutlet var videoPlayerView: UIView!
@IBOutlet var controlBtn: UIButton!
var moviePlayer:MPMoviePlayerController!
var url:NSURL = NSURL(string: "http://jplayer.org/video/m4v/Big_Buck_Bunny_Trailer.m4v")!
override func viewDidLoad() {
super.viewDidLoad()
}
func videoThumbnailIsAvailable(notification: NSNotification){
if let player = moviePlayer{
println("Thumbnail is available")
NSNotificationCenter.defaultCenter().addObserver(self,
selector: "videoThumbnailIsAvailable:",
name: MPMoviePlayerThumbnailImageRequestDidFinishNotification,
object: nil)
/* Capture the frame at the third second into the movie */
let thirdSecondThumbnail = 3.0
/* We can ask to capture as many frames as we
want. But for now, we are just asking to capture one frame
Ask the movie player to capture this frame for us */
moviePlayer.requestThumbnailImagesAtTimes([thirdSecondThumbnail],
timeOption: .NearestKeyFrame)
/* Now get the thumbnail out of the user info dictionary */
let thumbnail =
notification.userInfo![MPMoviePlayerThumbnailImageKey] as? UIImage
if let imageR = thumbnail{
/* We got the thumbnail image. You can now use it here */
println("Thumbnail image = \(imageR)")
//println(UIImage(data: imageR))
thumbnailImage.image = imageR
}
}
}
@IBAction func controlBtn(sender: AnyObject) {
controlBtn.alpha = 0
moviePlayer = MPMoviePlayerController(contentURL: url)
let frameWidth = self.videoPlayerView.frame.size.width
let frameHeight = self.videoPlayerView.frame.size.height
//moviePlayer.view.frame = CGRect(x: 24, y: 18, width: frameWidth, height: frameHeight)
self.videoPlayerView.addSubview(moviePlayer.view)
// Send button backword
self.videoPlayerView.sendSubviewToBack(moviePlayer.view)
moviePlayer.fullscreen = false
moviePlayer.controlStyle = MPMovieControlStyle.Embedded
// Pure Visual Format Language style (http://stackoverflow.com/questions/26180822/swift-adding-constraints-programmatically)
(moviePlayer.view).setTranslatesAutoresizingMaskIntoConstraints(false)
let views = ["view": videoPlayerView, "videoView": moviePlayer.view]
var constH = NSLayoutConstraint.constraintsWithVisualFormat("H:[view]-(<=0)-[videoView(\(frameWidth))]", options: .AlignAllCenterY, metrics: nil, views: views)
view.addConstraints(constH)
var constW = NSLayoutConstraint.constraintsWithVisualFormat("V:[view]-(<=0)-[videoView(\(frameHeight))]", options: .AlignAllCenterX, metrics: nil, views: views)
view.addConstraints(constW)
}
override func viewDidDisappear(animated: Bool) {
moviePlayer.stop()
}
}
Any help would be appreciated. Thanks.
Upvotes: 0
Views: 2123
Reputation: 2782
From your code it looks like your moviePlayer
property isn't defined until the controlBtn(sender)
action is called, so if you navigate away from this view controller without pushing that button first, moviePlayer
will be nil
when the view controller disappears.
override func viewDidDisappear(animated: Bool) {
super.viewDidDisappear(animated) ///< Don't for get this BTW!
if let player = self.moviePlayer {
player.stop()
}
}
Furthermore, your moviePlayer
property should be an optional instead of an implicitly unwrapped optional. That's the point of optionals—they prevent you from making these mistakes and having crashes like the one you're experiencing.
var moviePlayer: MPMoviePlayerController?
Upvotes: 3