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)
Hay un segmento de desenrollado especial destinado a hacer retroceder la pila de vistas a cierto controlador de vista. Por favor, vea mi respuesta aquí: ¿cómo descartar el controlador de 2 vistas en ios Swift?
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)
}