Я хочу воспроизвести локальное видео в AVPlayerViewController, но не нашел событие нажатия кнопки "Готово".
Мое видео может воспроизводиться в AVPlayerViewController, но я не нашел следующую кнопку, предыдущую кнопку и событие нажатия кнопки мыши.
Я хочу воспроизвести локальное видео в AVPlayerViewController, но не нашел событие нажатия кнопки "Готово".
Мое видео может воспроизводиться в AVPlayerViewController, но я не нашел следующую кнопку, предыдущую кнопку и событие нажатия кнопки мыши.
Официально нет события щелчка кнопки Done Button, об этом сказал инженер из Apple здесь.
Что касается моих исследований, я узнал, что есть один, но действительно косвенный способ получить событие, если нажата кнопка "Готово" .
Я узнал, что нажата единственная переменная AVPlayerViewController, которая изменяется при нажатии кнопки AVPlayerViewController.view.frame
.
Прежде всего view.frame появляется в центре viewController.
Если вы представляете его с помощью animated : true
, он переходит в нижнюю часть viewController и обратно в центр. Когда это делается, щелчок возвращается к нижней части.
Если вы представляете его с помощью animated : false
, будет только 2 изменения: рамка будет находиться в центре viewController, когда вы начнете воспроизводить видео, а внизу, когда нажата кнопка "Готово" .
Итак, если вы добавите наблюдателя в AVPlayerViewController.view.frame
в обратном вызове на present(PlayerViewController, animated : true)
, вы получите только один вызов наблюдателя, сразу после нажатия кнопки мыши и просмотра видео будет вне экрана.
В моем случае AVPlayerViewController был представлен модально с анимацией. Код ниже работал у меня:
Swift 3.0
override func viewDidLoad()
{
super.viewDidLoad()
let videoURL = NSURL(fileURLWithPath:Bundle.main.path(forResource: "MyVideo", ofType:"mp4")!)
let player = AVPlayer(url: videoURL as URL)
present(playerViewController, animated: false) { () -> Void in
player.play()
self.playerViewController.player = player
self.playerViewController.addObserver(self, forKeyPath: #keyPath(UIViewController.view.frame), options: [.old, .new], context: nil)
}}
override func observeValue(forKeyPath keyPath: String?,
of object: Any?,
change: [NSKeyValueChangeKey : Any]?,
context: UnsafeMutableRawPointer?)
{
print(self.playerViewController.view.frame)
//Player view is out of the screen and
//You can do your custom actions
}
Кроме того, я узнал, когда вы нажимаете "Готово" , AVPlayerViewController не отклоняется, и вы можете видеть его в ParentViewController.presentedViewController
, поэтому вы не можете добавить наблюдателя в это свойство
Я сделал это, чтобы получить событие нажатия кнопки Done
с AVPlayerViewController
.
Прежде всего, создайте расширение Notification.Name
, как показано ниже.
extension Notification.Name {
static let kAVPlayerViewControllerDismissingNotification = Notification.Name.init("dismissing")
}
Теперь создайте расширение AVPlayerViewController
и переопределите viewWillDisappear
, как показано ниже.
// create an extension of AVPlayerViewController
extension AVPlayerViewController {
// override 'viewWillDisappear'
open override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
// now, check that this ViewController is dismissing
if self.isBeingDismissed == false {
return
}
// and then , post a simple notification and observe & handle it, where & when you need to.....
NotificationCenter.default.post(name: .kAVPlayerViewControllerDismissingNotification, object: nil)
}
}
ЭТО ДЛЯ ТОЛЬКО ОСНОВНОЙ ФУНКЦИОНАЛЬНОСТИ, КОТОРЫЕ РАБОТАЮТ СОБЫТИЮ СОВМЕСТНОГО КНОПКА.
счастливое кодирование...
Это небольшое улучшение от ответа @vmchar:
Мы можем использовать метод .isBeingDismissed, чтобы гарантировать, что AVPlayerViewController закрывается вместо анализа кадра.
...
let videoURL = NSURL(fileURLWithPath:"video.mp4")
let player = AVPlayer(url: videoURL as URL)
present(playerViewController!, animated: false) { () -> Void in
player.play()
self.playerViewController!.player = player
self.playerViewController!.addObserver(self, forKeyPath:#keyPath(UIViewController.view.frame), options: [.old, .new], context: nil)
...
Затем для наблюдения значения
override func observeValue(forKeyPath keyPath: String?,
of object: Any?,
change: [NSKeyValueChangeKey : Any]?,
context: UnsafeMutableRawPointer?)
{
if (playerViewController!.isBeingDismissed) {
// Video was dismissed -> apply logic here
}
}
Самым простым решением для меня было создать подкласс AVPlayerViewController
и добавить в него простой блок завершения.
class MYVideoController: AVPlayerViewController {
typealias DissmissBlock = () -> Void
var onDismiss: DissmissBlock?
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
if isBeingDismissed {
onDismiss?()
}
}
}
Usage
Usage...
let avPlayerViewController = MYVideoController()
avPlayerViewController.onDismiss = { [weak self] in
print("dismiss")
}
Вы можете использовать
override func viewWillAppear(_ animated: Bool) {
print("Done Button Click Event")
}
В вашем классе. Когда AVPlayerViewController исчезнет, тогда вызовите funWillAppear func, и вы можете сделать свою работу здесь.
Если вы используете класс AVPlayerViewController, вы можете использовать эту функцию.
override func viewWillDisappear(_ animated: Bool) {
<#code#>
}
У меня была та же проблема, и я нашел еще один трюк (работает с быстрой платформой YoutubePlayer, которая воспроизводит видео в веб-просмотре, но вы можете адаптировать его к другим приложениям).
В моем случае нажатие кнопки Done
и нажатие кнопки Pause
на полноэкранном видеоплеере приводит к событию Pause
на YoutubePlayer. Однако, когда видео воспроизводится в другом окне, я подклассифицировал основное окно приложения и переопределил функции becomeKey
и resignKey
, чтобы сохранить, является ли мое окно ключевым окном или нет, например:
class MyWindow:UIWindow {
override func becomeKey() {
Services.appData.myWindowIsKey = true
}
override func resignKey() {
Services.appData.myWindowIsKey = false
}
}
Как только у меня есть это, я могу проверить, является ли мое окно ключевым, когда состояние видео переходит в паузу - когда была нажата кнопка Done
, мое окно , и я могу отклонить мой контроллер видеорекламы, а в случае Pause
мое окно не в ключевом окне, поэтому я ничего не делаю.
Я думаю, что есть много способов снять кожу с кошки. Мне нужно было обработать событие клика "Готово". В моем случае я хотел убедиться, что я смог подключиться к событию после нажатия кнопки "X", и AVPlayerViewController был полностью закрыт (отклонен).
Swift 4.0
protocol TableViewCellVideoPlayerViewControllerDelegate: class {
func viewControllerDismissed()
}
class MyPlayerViewController: AVPlayerViewController {
weak var navDelegate: TableViewCellVideoPlayerViewControllerDelegate?
open override func viewDidDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
if self.isBeingDismissed {
self.navDelegate?.viewControllerDismissed()
}
}
}
class TodayCell: UITableViewCell, SFSafariViewControllerDelegate, TableViewCellVideoPlayerViewControllerDelegate {
func viewControllerDismissed() {
self.continueJourney()
}
}
Целевая версия c: (на основе ответа vmchar)
- (void)viewDidLoad
{
[super viewDidLoad];
NSURL *url = [NSURL fileURLWithPath:path];
AVPlayer *player = [AVPlayer playerWithURL:url];
AVPlayerViewController *AVPlayerVc = [[AVPlayerViewController alloc] init];
if (AVPlayerVc) {
[self presentViewController:AVPlayerVc animated:YES completion:^{
[player play];
AVPlayerVc.player = player;
[AVPlayerVc addObserver:self forKeyPath:@"view.frame" options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionInitial) context:nil];
}];
}
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if ([keyPath isEqualToString:@"view.frame"]) {
CGRect newValue = [change[NSKeyValueChangeNewKey]CGRectValue];
CGFloat y = newValue.origin.y;
if (y != 0) {
NSLog(@"Video Closed");
}
}
}
Вы можете посмотреть этот fooobar.com/info/710733/... и вот проект github для справки. Вы должны будете использовать это:
self.showsPlaybackControls = true
Также обратите внимание на Документация Apple