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

问题描述:

我有一个videPlayerView,它上面有ContainerView来显示activityIndi​​catorView。当我从单元格中的一个collectionView中选择一个项目时,该视图被加载。我的问题是如何使用cancelButton以除去这种观点,我试图removeFromSuperview()用于容器都和playerView但与此错误如何从superView中删除自定义playerView?

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) 




     } 



    } 


} 

有这关系到你改变主线程之外的用户界面的机会。

从UIView的文件
“线程注意事项
手法到应用程序的用户界面在主线程必须发生。因此,您应该始终使用应用程序主线程中运行的代码调用类的方法。唯一可能不是严格需要的是创建视图对象本身,但所有其他操作应该在主线程上进行。

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

你取消回调大概应该是如下

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

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

感谢您的回答SPAD的。我得到一个编译器错误为self.view(价值的类型VideoplayerView没有成员视图。我试图直接删除VideoplayerView但我得到了错误。终止与未捕获异常类型NSException – user8249883

+0

是'视图'是一个错字。应该可以从ViewController管理VideoPlayerView的可见性而不是视图本身,崩溃很可能是由于你在运行代码的时候删除了视图 – Spads

+0

是的,这个问题我最终实现了UIPanGesturerecognizer,就像在youtube上一样现在它终于有效了,谢谢。 – user8249883