2017-07-23 5 views
0

J'ai un videPlayerView qui a ContainerView sur le dessus pour montrer activityIndicatorView. La vue est chargée lorsque je sélectionne un élément d'une collectionVue dans une cellule. Ma question est de savoir comment supprimer ce point de vue à l'aide du cancelButton, j'ai essayé removeFromSuperview() pour le conteneur et le playerView mais les application se bloque avec cette erreurComment supprimer un lecteur de vue personnalisé de superView?

AQDefaultDevice (1): sauter flux d'entrée 0 0 0x0

Voici le code:

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) 




     } 



    } 


} 

Répondre

0

Il y a une chance cela est lié à vous changer l'interface utilisateur en dehors du thread principal.

à partir de documents UIView
« Threading Considérations
Manipulations à l'interface utilisateur de votre application doit se produire sur le thread principal. Ainsi, vous devez toujours appeler les méthodes de la classe UIView à partir du code s'exécutant dans le thread principal de votre application. La seule fois où cela n'est pas strictement nécessaire est lors de la création de l'objet de vue lui-même, mais toutes les autres manipulations doivent avoir lieu sur le thread principal.

De même, votre fonction d'annulation crée une nouvelle vue de lecteur vidéo, puis tente de la supprimer de son parent, ce qui ne semble pas correct.

Votre rappel devrait annuler probablement comme suit

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

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

Merci pour les Spad de réponse. Je reçois une erreur complier pour self.view (Valeur de type VideoplayerView n'a pas de membre View.J'ai essayé d'enlever le VideoplayerView directement mais j'ai eu l'erreur.terminant avec une exception uncaught de type NSException – user8249883

+0

Ouais la 'vue' était une faute de frappe. devrait probablement gérer la visibilité de VideoPlayerView à partir d'un ViewController pas la vue elle-même.Ce crash est probablement dû à la suppression de la vue lors de l'exécution du code à l'intérieur – Spads

+0

Oui, c'était le problème. et ça marche enfin maintenant, merci. – user8249883