I have programmatically added an AVPlayerViewController
to a UIViewController
. I am able to receive the notification when the player is finished playing (playerDidFinishPlaying). I would also like to know if a user has touched the screen while the video is playing and I have not found any related notifications.

- 344
- 2
- 24

- 2,230
- 18
- 34
-
How to detect touch when user pressed forward/backward button? – pkc456 Oct 03 '17 at 11:55
3 Answers
The solution is to create a Base class of AVPlayerViewController
and override touchesBegan(_:with:) method:
Swift 2:
Custom Base Class:
class CustomAVPlayerViewController: AVPlayerViewController {
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
print("touchesBegan")
}
}
ViewController:
let videoURL = NSURL(string: "https://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4")
let player = AVPlayer(URL: videoURL!)
let playerViewController = CustomAVPlayerViewController()
playerViewController.player = player
self.presentViewController(playerViewController, animated: true) {
playerViewController.player!.play()
}
Swift 3:
Custom Base Class:
class CustomAVPlayerViewController: AVPlayerViewController {
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
print("touchesBegan")
}
}
View Controller:
let videoURL = URL(string: "https://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4")
let player = AVPlayer(url: videoURL!)
let playerViewController = CustomAVPlayerViewController()
playerViewController.player = player
self.present(playerViewController, animated: true) {
playerViewController.player!.play()
}
Don't forget to import AVKit
and import AVFoundation
.
Each time you tap on the playerViewController
, "touchesBegan" will be printed.

- 30,560
- 17
- 97
- 143
-
2Any thoughts about the reference documentation: _Do not subclass AVPlayerViewController. Overriding this class’s methods is unsupported and results in undefined behavior_. – Bruce Oct 06 '16 at 15:13
-
1Referring to @Bruce's comment ([Apple Documentation](https://developer.apple.com/reference/avkit/avplayerviewcontroller)): _touchesBegan_ is a [UIResponder] (https://developer.apple.com/reference/uikit/uiresponder) method (UIResponder->UIViewController->AVPlayerViewController). In our case, UIResponder should take care of touch events, it is not related to the core functionality of the AVPlayerViewController i.e overriding this method does not reflect on how AVPlayerViewController handles working with a video -for example-, methods that do this should NOT be overridden. thanks for the note. – Ahmad F Oct 06 '16 at 16:37
-
@AhmadF, How to detect touch when user pressed forward/backward button? – pkc456 Oct 03 '17 at 11:52
-
This is not a clean solution. The correct way is to put gesture recognizers into the AVPlayerViewController's contentOverlayView. See my reply (Objective C source, sorry) to https://stackoverflow.com/questions/36878609/avplayer-uitapgesturerecognizer-not-working – TyR Feb 14 '18 at 23:45
-
I had this same problem. The contentOverlayView is only available in tvos, so that was not an option.
I ended up adding a UIView over the UIImageView that I added the AVPlayer to. I set the background color to clear on the UIView, so it's not visible, but can receive gestures. This provides a target for the tap gesture recognizer.

- 41
- 5
I resolve the same. Subclassing AVPlayerViewController will work on iOS 11.4.1 but not on iOS 12 an above. So the solution for this is add subview on playerviewcontroller contentoverlayview and then on that subview you can add any gesture or button for detecting the touch. Here is the code snippet for the same::
// This notification is added for continuous playing of the video you can remove this in case you need video is played only once.
private func playVideo() {
guard let path = Bundle.main.path(forResource: "BG01", ofType:"mp4") else {
debugPrint("video.m4v not found")
return
}
self.player = AVPlayer(url: URL(fileURLWithPath: path))
NotificationCenter.default.addObserver(forName: .AVPlayerItemDidPlayToEndTime, object: self.player?.currentItem, queue: .main) { [weak self] _ in
self?.player?.seek(to: kCMTimeZero)
self?.player?.play()
}
let playerController : AVPlayerViewController? = AVPlayerViewController()
let btn : UIButton = UIButton()
btn.frame = CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: self.view.frame.size.height)
btn.addTarget(self, action: #selector(touchDetect), for: .touchUpInside)
btn.backgroundColor = UIColor.clear
playerController?.contentOverlayView?.addSubview(btn)
// playerController?.homeVCProtocolDelegate = self as HomeVCProtocol
playerController?.player = player
playerController?.showsPlaybackControls = false
self.player?.play()
present(playerController!, animated: false) {
self.player?.play()
}
}
@objc func touchDetect()
{
// Here you will get the call
}

- 13,780
- 10
- 33
- 38

- 41
- 1