I'm currently looping my mp4 video with no playback controls, kind of like a gif but with sound. But I do not know why when I segue to the next view controller, the video is still playing. Does anybody know the simplest method to resolve this issue?
ViewController
import UIKit
import AVKit
import AVFoundation
fileprivate var playerObserver: Any?
class ScoreController: UIViewController {
@IBOutlet var label: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
let returnValue: Int = UserDefaults.standard.integer(forKey: "userScore")
label.text = "Your Score: \(returnValue)/30"
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
let path = Bundle.main.path(forResource: "Innie-Kiss", ofType:"mp4")
let player = AVPlayer(url: URL(fileURLWithPath: path!))
let resetPlayer = {
player.seek(to: kCMTimeZero)
player.play()
}
playerObserver = NotificationCenter.default.addObserver(forName: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: player.currentItem, queue: nil) { notification in resetPlayer() }
let controller = AVPlayerViewController()
controller.player = player
controller.showsPlaybackControls = false
self.addChildViewController(controller)
let screenSize = UIScreen.main.bounds.size
let videoFrame = CGRect(x: 0, y: 130, width: screenSize.width, height: (screenSize.height - 130) / 2)
controller.view.frame = videoFrame
self.view.addSubview(controller.view)
player.play()
} catch {
}
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
}
fileprivate var player: AVPlayer? {
didSet { player?.play() }
}
deinit {
guard let observer = playerObserver else { return }
NotificationCenter.default.removeObserver(observer)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
@IBAction func doneButton(_ sender: Any) {
self.performSegue(withIdentifier: "done", sender: self)
}
}
Besides AVPlayer, apple has also provided the support for a full screen controller for media playback. AVPlayerViewController — An object that displays the video content from a player object along with system-supplied playback controls. It is provided by AVKit framework. Line 1 — create an AVPlayerViewController instance.
For example, we could use a loader to show the playback status on screen. AVPlayer’s timeControlStatus can be used to track the video playback status. timeControlStatus — A status that indicates whether playback is currently in progress, paused indefinitely, or suspended while waiting for appropriate network conditions.
You can use an AVPlayer to play local and remote file-based media, such as QuickTime movies and MP3 audio files, as well as audiovisual media served using HTTP Live Streaming. Line 1 — AVAsset object is created using the video URL.
How to use Swift to detect when AVPlayer video ends playing? To detect the end of a video in swift we’ll need to create a video player, then use notifications to detect when the video stops playing. We’ll do this with help of an example in swift.
In viewWillDisapper() or button action for segue do this :
NotificationCenter.default.removeObserver(self)
Also move this from viewDidLoad() to some function like :
var player: AVPlayer?
func audioPlayer(){
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
let path = Bundle.main.path(forResource: "Innie-Kiss", ofType:"mp4")
player = AVPlayer(url: URL(fileURLWithPath: path!))
let resetPlayer = {
self.player?.seek(to: kCMTimeZero)
self.player?.play()
}
playerObserver = NotificationCenter.default.addObserver(forName: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: player?.currentItem, queue: nil) { notification in resetPlayer() }
let controller = AVPlayerViewController()
controller.player = player
controller.showsPlaybackControls = false
self.addChildViewController(controller)
let screenSize = UIScreen.main.bounds.size
let videoFrame = CGRect(x: 0, y: 130, width: screenSize.width, height: (screenSize.height - 130) / 2)
controller.view.frame = videoFrame
self.view.addSubview(controller.view)
player?.play()
} catch {
}
}
and make player object a global variable. var player = AVPlayer?
and in viewWillDisappear
make it nil
.
So your viewWillDisappear should look like this :
override func viewWillDisappear(_ animated: Bool) {
NotificationCenter.default.removeObserver(self)
if player != nil{
player?.replaceCurrentItem(with: nil)
player = nil
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With