close ios swift viewcontroller dismiss

ios - close - Descartar más de un controlador de vista simultáneamente.



swift 4 dismiss viewcontroller (5)

Deberías poder llamar:

self.presentingViewController.dismissViewControllerAnimated(true, completion: {});

(Es posible que necesites agregar ? O ! algún lugar, no soy un desarrollador rápido)

Estoy haciendo un juego usando SpriteKit. Tengo 3 viewControllers: seleccionando el nivel vc, game vc y win vc. Una vez finalizado el juego, quiero mostrar el vc ganador, luego, si presiono el botón Aceptar en el vc ganador, quiero descartar el vc ganador Y el juego vc (saca dos controladores de vista de la pila). Pero no sé cómo hacerlo porque si llamo

self.dismissViewControllerAnimated(true, completion: {})

la victoria vc (parte superior de la pila) se descarta, por lo que no sé dónde llamarla nuevamente para descartar el juego vc. ¿Hay alguna manera de que pueda solucionar esto sin usar el controlador de navegación?

Este es el primer VC: (Por favor, preste atención a mis comentarios que comienzan con "//")

class SelectLevelViewController: UIViewController { // I implemented a UIButton on its storyboard, and its segue shows GameViewController override func viewDidLoad() { super.viewDidLoad() } }

Este es el segundo VC:

class GameViewController: UIViewController, UIPopoverPresentationControllerDelegate { var scene: GameScene! var stage: Stage! var startTime = NSTimeInterval() var timer = NSTimer() var seconds: Double = 0 var timeStopped = false var score = 0 @IBOutlet weak var targetLabel: UILabel! @IBOutlet var displayTimeLabel: UILabel! @IBOutlet weak var scoreLabel: UILabel! @IBOutlet weak var gameOverPanel: UIImageView! @IBOutlet weak var shuffleButton: UIButton! @IBOutlet weak var msNum: UILabel! var mapNum = Int() var stageNum = Int() var tapGestureRecognizer: UITapGestureRecognizer! override func viewDidLoad() { super.viewDidLoad() let skView = view as! SKView skView.multipleTouchEnabled = false scene = GameScene(size: skView.bounds.size) scene.scaleMode = .AspectFill msNum.text = "/(mapNum) - /(stageNum)" stage = Stage(filename: "Map_0_Stage_1") scene.stage = stage scene.addTiles() scene.swipeHandler = handleSwipe gameOverPanel.hidden = true shuffleButton.hidden = true skView.presentScene(scene) Sound.backgroundMusic.play() beginGame() } func beginGame() { displayTimeLabel.text = String(format: "%ld", stage.maximumTime) score = 0 updateLabels() stage.resetComboMultiplier() scene.animateBeginGame() { self.shuffleButton.hidden = false } shuffle() startTiming() } func showWin() { gameOverPanel.hidden = false scene.userInteractionEnabled = false shuffleButton.hidden = true scene.animateGameOver() { self.tapGestureRecognizer = UITapGestureRecognizer(target: self, action: "hideWin") self.view.addGestureRecognizer(self.tapGestureRecognizer) } } func hideWin() { view.removeGestureRecognizer(tapGestureRecognizer) tapGestureRecognizer = nil gameOverPanel.hidden = true scene.userInteractionEnabled = true self.performSegueWithIdentifier("win", sender: self) // this segue shows WinVC but idk where to dismiss this GameVC after WinVC gets dismissed... } func shuffle() {...} func startTiming() {...} }

Y este es el 3º VC:

class WinVC: UIViewController { @IBOutlet weak var awardResult: UILabel! @IBAction func dismissVC(sender: UIButton) { self.dismissViewControllerAnimated(true, completion: {}) // dismissing WinVC here when this button is clicked } override func viewDidLoad() { super.viewDidLoad() } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } }


El comentario de @Ken Toh fue lo que funcionó para mí en esta situación: desconexión de llamada desde el controlador de vista que desea mostrar después de que se descarte todo lo demás.

Si tiene una "pila" de 3 controladores de vista presentados A , B y C , donde C está en la parte superior, al llamar a A.dismiss(animated: true, completion: nil) descartará B y C simultáneamente.

Si no tiene una referencia a la raíz de la pila, puede encadenar un par de accesos a presentingViewController para acceder a ella. Algo como esto:

self.presentingViewController?.presentingViewController?.dismiss(animated: true, completion: nil)



Puede descartar el controlador de presentación de WinVC (GameViewController) en el bloque de finalización:

let presentingViewController = self.presentingViewController self.dismissViewControllerAnimated(false, completion: { presentingViewController?.dismissViewControllerAnimated(true, completion: {}) })

Alternativamente, puede comunicarse con el controlador de vista de raíz y llamar a despide a ViewControllerAnimated, que descartará ambos controladores de vista modales en una sola animación:

self.presentingViewController?.presentingViewController?.dismissViewControllerAnimated(true, completion: {})


Tuve algunos problemas de animación al intentar la respuesta aceptada en mi aplicación. Las vistas presentadas anteriormente parpadearían o tratarían de animar en la pantalla. Esta fue mi solución:

if let first = presentingViewController, let second = first.presentingViewController, let third = second.presentingViewController { second.view.isHidden = true first.view.isHidden = true third.dismiss(animated: true) }