NS1518
NS1518

Reputation: 838

iOS Swift stopping MoviePlayer on view dismiss

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

Answers (1)

Patrick Lynch
Patrick Lynch

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

Related Questions