Как перейти к AVPlayerViewController из пользовательского представления? - PullRequest
0 голосов
/ 17 мая 2018

У меня есть пользовательское представление:

class MediaPlayerView: UIView {

    var mediaURL: URL? {
        didSet {
            determineMediaType()
        }
    }
    let videoExtensions = ["mov"]

    override init (frame : CGRect) {
        super.init(frame : frame)
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    func determineMediaType() {
        let url = self.mediaURL
        let pathExtention = url?.pathExtension
        if videoExtensions.contains(pathExtention!) {
            print("Movie URL: \(String(describing: url))")
            setupVideo(url: url!)
        } else {
            print("Image URL: \(String(describing: url))")
            setupImage(url: url!)
        }
    }

    func setupVideo(url: URL) {
        let playButton = UIImage(named: "Play Triangle")
        let playButtonView = UIImageView(image: playButton!)
        let singleTap = UITapGestureRecognizer(target: self,  action: #selector(tapDetected))
        playButtonView.addGestureRecognizer(singleTap)
        playButtonView.center = self.center
        playButtonView.frame.size.width  = self.frame.size.width/5
        playButtonView.frame.size.height = self.frame.size.height/5
        playButtonView.autoresizingMask = [.flexibleWidth,.flexibleHeight]
        playButtonView.isUserInteractionEnabled = true
        self.addSubview(playButtonView)
    }

    @objc func tapDetected() {
        print("tap!")

        let player = AVPlayer(url: self.mediaURL!)
        let controller = AVPlayerViewController()
        controller.player = player
        self.window?.rootViewController?.present(controller, animated: true) {
            player.play()
        }
    }

    func setupImage(url: URL) {
        let imageView = UIImageView()
        imageView.frame = self.bounds
        imageView.autoresizingMask = [.flexibleWidth,.flexibleHeight]
        self.addSubview(imageView)
        imageView.kf.setImage(with: url)
    }

}

Однако, когда я нажимаю кнопку воспроизведения, я получаю следующую ошибку:

Warning: Attempt to present <AVPlayerViewController: 0x7fe8b200b000> on <SweatNet.MainTabBarController: 0x7fe8b4816400> whose view is not in the window hierarchy!

Он появляется в этой строке: self.window? .rootViewController? .present.Я думаю, что меня смущает вызов rootViewController (который выглядит как SweatNet.MainTabBarController).Я хочу ему позвонить SweatNet.TagViewController.Это тот, который содержит ячейку, которая содержит пользовательский MediaPlayerView, но я не понимаю, как получить ссылку на это.

Ответы [ 2 ]

0 голосов
/ 03 июня 2018

Мне было бы интересно получить некоторые отзывы об этом ответе, так как я думаю, что это пример того, как я думаю о системе iOS неправильно.В конце концов я понял, что пытался поместить код контроллера представления в собственное представление.Просмотр кода контроллера, являющегося кодом для запуска AVPlayerViewController.Скорее я должен поместить эту логику в мой контроллер представления.

То, что я сделал, работает, используя метод делегата collectionView didSelectItemAt indexPath: IndexPath внутри контроллера представления, где логика контроллера представления для представления коллекции хранится следующим образом:

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    if collectionView == self.collectionView {
        let post = posts[indexPath.row]
        if post.isVideo == true {
            self.performSegue(withIdentifier: "playVideo", sender: nil)
        } else {
            print("is image. might go full screen one day here")
        }
}

Этоработает, и я считаю, что лучше, чем написать собственный аспект представления, запустить AVPlayerViewController.Но также возможно, что оба подхода работают - я действительно недостаточно знаю о разработке iOS, чтобы сделать этот вызов.Любые комментарии приветствуются.

0 голосов
/ 17 мая 2018

Попробуйте это:

class func topViewController(controller: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController? {
    if let navigationController = controller as? UINavigationController {
        return topViewController(controller: navigationController.visibleViewController)
    }
    if let tabController = controller as? UITabBarController {
        if let selected = tabController.selectedViewController {
            return topViewController(controller: selected)
        }
    }
    if let presented = controller?.presentedViewController {
        return topViewController(controller: presented)
    }
    return controller
}

Напишите ваш метод как:

@objc func tapDetected() {
    print("tap!")

    let player = AVPlayer(url: self.mediaURL!)
    let controller = AVPlayerViewController()
    controller.player = player
    topViewController().present(controller, animated: true) {
        player.play()
    }
}

Это вернет вам верхний vc в иерархии.Надеюсь, это поможет!

...