web-dev-qa-db-fra.com

Fait un clic sur un événement dans AVPlayerViewController

Je souhaite lire une vidéo locale dans AVPlayerViewController mais je n'ai pas trouvé l'événement de clic du bouton Terminé.

Ma vidéo peut être lue dans AVPlayerViewController, mais je n'ai pas trouvé le bouton suivant, le bouton précédent et l'événement de clic sur le bouton Terminé. 

9
Yogendra Patel

Officiellement, il n'y a pas d'événement de clic sur le bouton Terminé, a déclaré un ingénieur d'Apple à ce sujet ici

En ce qui concerne mes recherches, j’ai découvert qu’il existait un moyen indirect, mais vraiment indirect, d’obtenir un événement si le bouton Terminé était cliqué.

J'ai découvert que la seule variable d'AVPlayerViewController, qui change lorsque l'on clique sur le bouton, est AVPlayerViewController.view.frame. Tout d’abord, view.frame apparaît au centre du viewController.

Si vous le présentez avec animated : true, il ira au bas de viewController et reviendra au centre. Lorsque vous avez terminé, vous revenez au bas de la page.

Si vous le présentez avec animated : false, il n'y aura que 2 changements: l'image sera au centre de viewController lorsque vous commencerez à lire la vidéo et en bas, lorsque vous cliquerez sur Terminé.

Donc, si vous ajoutez l'observateur au AVPlayerViewController.view.frame dans le rappel à present(PlayerViewController, animated : true), vous n'obtiendrez qu'un seul appel de l'observateur. Dès que vous avez terminé, le bouton est cliqué et l'affichage vidéo sort de l'écran.

Dans mon cas, AVPlayerViewController était présenté sous forme modale avec animation. Le code ci-dessous a fonctionné pour moi:

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
}

En outre, j'ai découvert que lorsque vous cliquez sur Terminé, AVPlayerViewController n'est pas renvoyé et vous pouvez le voir dans ParentViewController.presentedViewController, vous ne pouvez donc pas ajouter l'observateur à cette propriété.

14
vmchar


Je l’ai fait pour obtenir un événement de clic sur le bouton Done de AVPlayerViewController.

Tout d’abord, créez une extension de Notification.Name comme ci-dessous

extension Notification.Name {
static let kAVPlayerViewControllerDismissingNotification = Notification.Name.init("dismissing")
}

Maintenant, créez une extension de AVPlayerViewController et remplacez viewWillDisappear comme ci-dessous

// 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)
    }
}

CECI IS POUR UNE SEULE FONCTIONNALITÉ DE BASE QUI MANIPULE L'ÉVÉNEMENT DU BOUTON.

codage heureux ...

10
Vats

Ceci est une petite amélioration par rapport à la réponse de @vmchar: 

Nous pouvons utiliser la méthode .isBeingDismissed pour nous assurer que le AVPlayerViewController est en train d'être fermé au lieu d'analyser le cadre. 

...

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)
...

Puis observer la valeur 

override func observeValue(forKeyPath keyPath: String?,
                           of object: Any?,
                           change: [NSKeyValueChangeKey : Any]?,
                           context: UnsafeMutableRawPointer?)
{

    if (playerViewController!.isBeingDismissed) {  
     // Video was dismissed -> apply logic here
    } 
} 
1
Dipo Areoye

Je suppose qu'il y a beaucoup de façons de peler un chat. J'avais besoin de gérer l'événement de clic 'Terminé'. Dans mon cas, je voulais être sûr de pouvoir m'inscrire à l'événement après avoir cliqué sur le "X" et AVLayerViewController était COMPLÈTEMENT fermé (rejeté). 

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()
    }
 }
0
Clay Martin

J'ai eu le même problème et j'ai trouvé une autre astuce (fonctionne avec le framework YoutubePlayer Swift qui lit les vidéos dans une webview, mais vous pourrez peut-être l'adapter à d'autres utilisations).

Dans mon cas, appuyer sur le bouton Done et sur le bouton Pause du lecteur vidéo plein écran provoque un événement pause sur YoutubePlayer. Cependant, lorsque la vidéo est lue dans une fenêtre différente, j'ai sous-classé la fenêtre principale de mon application et substitué les fonctions becomeKey et resignKey pour stocker si ma fenêtre est la fenêtre de clé ou non, comme ceci:

class MyWindow:UIWindow {
    override func becomeKey() {
        Services.appData.myWindowIsKey = true
    }

    override func resignKey() {
        Services.appData.myWindowIsKey = false
    }
}

Une fois que j'ai cela, je peux vérifier si ma fenêtre est la clé lorsque l'état de la vidéo passe en pause - lorsque vous appuyez sur le bouton Done, ma fenêtre est la fenêtre de la clé et je peux fermer mon contrôleur de vue vidéo, et Pause cas ma fenêtre n'est pas la fenêtre de clé, donc je ne fais rien.

0
TheEye