2017-07-23 75 views
0

我有一個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) 




     } 



    } 


} 

回答

0

有這關係到你改變主線程之外的用戶界面的機會。

從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

相關問題