如何从superView中删除自定义playerView?

时间:2017-07-23 00:19:57

标签: swift view avfoundation avplayer dismiss

我有一个videPlayerView,它上面有ContainerView来显示activityIndi​​catorView。当我从单元格内的collectionView中选择一个项目时,视图会被加载。我的问题是如何使用cancelButton删除此视图,我为容器和playerView尝试了removeFromSuperview()但应用程序崩溃时出现此错误

  

AQDefaultDevice(1):跳过输入流0 0 0x0

以下是代码:

class VideoPlayerView: UIView {
    var videoUrl: String!
    var uuidd: String!


    let activityIndicatorView: UIActivityIndicatorView = {
        let aiv = UIActivityIndicatorView(activityIndicatorStyle: .whiteLarge)
        aiv.translatesAutoresizingMaskIntoConstraints = false
        aiv.startAnimating()

        return aiv
    }()



    lazy var controlsContainerView: UIView = {
        let view = UIView()
        view.backgroundColor = UIColor(white: 0, alpha: 1)
        view.isUserInteractionEnabled = true


        view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handlezoomout)))

        return view
    }()

    func handlezoomout(hh: UITapGestureRecognizer){
        print("n3me")


}


    lazy var cancelButton: UIButton = {
        let cancelButton = UIButton()
        cancelButton.setImage(#imageLiteral(resourceName: "cancel"), for: UIControlState())
        cancelButton.addTarget(self, action: #selector(cancel), for: .touchUpInside)
        return cancelButton
    }()

    func cancel() {

        controlsContainerView.removeFromSuperview()
        let video = VideoPlayerView()
        video.removeFromSuperview()


    }







    lazy var pausePlayButton: UIButton = {
        let button = UIButton(type: .system)
        let image = UIImage(named: "pause")
        button.setImage(image, for: UIControlState())
        button.translatesAutoresizingMaskIntoConstraints = false
        button.tintColor = .white
        button.isHidden = true

        button.addTarget(self, action: #selector(handlePause), for: .touchUpInside)

        return button
    }()


    var isPlaying = false

    func handlePause() {
        if isPlaying {
            player?.pause()
            pausePlayButton.setImage(UIImage(named: "play"), for: UIControlState())
        } else {
            player?.play()
            pausePlayButton.setImage(UIImage(named: "pause"), for: UIControlState())
        }

        isPlaying = !isPlaying
    }


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



        setUpPlayerView()

      controlsContainerView.frame = frame
      addSubview(controlsContainerView)



        cancelButton.frame = CGRect(x: 16.0, y: 20.0, width: 30.0, height: 30.0)
        controlsContainerView.addSubview(cancelButton)


        controlsContainerView.addSubview(activityIndicatorView)
        activityIndicatorView.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
        activityIndicatorView.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true

        controlsContainerView.addSubview(pausePlayButton)
        pausePlayButton.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
        pausePlayButton.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
        pausePlayButton.widthAnchor.constraint(equalToConstant: 50).isActive = true
        pausePlayButton.heightAnchor.constraint(equalToConstant: 50).isActive = true
        backgroundColor = UIColor.black



    }




    var player: AVPlayer?

    fileprivate func setUpPlayerView() {

    let postQuery = PFQuery(className: "posts")
    postQuery.whereKey("uuid", equalTo: PostUuidGlobalVariable.postuuid.last!)
    postQuery.getFirstObjectInBackground { (object, error) in
    if (error == nil && object != nil) {
    let videoFile = object!["video"] as! PFFile

    if let url = URL (string: videoFile.url!) {
     self.player = AVPlayer(url: url)

    let playerLayer = AVPlayerLayer(player: self.player)
    self.layer.addSublayer(playerLayer)
    playerLayer.frame = self.frame





    self.player?.play()
        self.player?.isMuted = false

    self.player?.addObserver(self, forKeyPath: "currentItem.loadedTimeRanges", options: .new, context: nil)

        NotificationCenter.default.addObserver(self, selector: #selector(self.playerDidFinishPlaying(note:)),
                                               name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: self.player?.currentItem)


    }
    }
    }
    }




    func playerDidFinishPlaying(note: NSNotification) {




    }



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

        //this is when the player is ready and rendering frames
        if keyPath == "currentItem.loadedTimeRanges" {
            activityIndicatorView.stopAnimating()


            pausePlayButton.isHidden = false
            isPlaying = true
        }
    }




    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}


class VideoLauncher: NSObject {




    func showVideoPlayer() {

        if let keyWindow = UIApplication.shared.keyWindow {
            let view = UIView(frame: keyWindow.frame)
            view.isUserInteractionEnabled = true
            view.backgroundColor = UIColor.white
            view.frame = CGRect(x: keyWindow.frame.width - 10, y: keyWindow.frame.height - 10, width: 10, height: 10)




            let height = keyWindow.frame.height
            let videoPlayerFrame = CGRect(x: 0, y: 0, width: keyWindow.frame.width, height: height)


            let videoPlayerView = VideoPlayerView(frame: videoPlayerFrame)



            view.addSubview(videoPlayerView)




            UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseOut, animations: {

                view.frame = keyWindow.frame

            }, completion: { (completedAnimation) in

                //maybe we'll do something here later...





                UIApplication.shared.isStatusBarHidden = true
            })

            keyWindow.addSubview(view)




        }



    }


}

1 个答案:

答案 0 :(得分:0)

这有可能与您更改主线程之外的用户界面有关。

来自UIView文件
'线程注意事项
必须在主线程上对应用程序的用户界面进行操作。因此,你应该总是调用方法 的UIView  来自应用程序主线程中运行的代码的类。这可能不是绝对必要的唯一时间是创建视图对象本身,但所有其他操作应该在主线程上发生。'

此外,您的取消功能会创建一个新的视频播放器视图,然后尝试将其从父视图中删除,这看起来不正确。

您的取消回调应该如下

func cancel() {
    DispatchQueue.main.async { [unowned self] in
        // to remove controls
        self.controlsContainerView.removeFromSuperview()

        // to remove video player view
        self.view.removeFromSuperview()
    }
}