Mostrar un UIAlertController en GameScene (SpriteKit / Swift)

La manera simple de mostrar un UIAlertView, en swift es:

let alert = UIAlertView() alert.title = "Alert!" alert.message = "A wise message" alert.addButtonWithTitle("Ok, thank you") alert.show() 

Pero esto ahora se deprecia en iOS 9 y recomienda usar UIAlertController :

 let myAlert: UIAlertController = UIAlertController(title: "Alert!", message: "Oh! Fancy", prefernetworkingStyle: .Alert) myAlert.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil)) self.presentViewController(myAlert, animated: true, completion: nil) 

Lo cual es genial, pero estoy usando SpriteKit y dentro de un GameScene, lo que da un error de Value of type 'GameScene' has no member 'presentViewController'

¿Necesito volver a mi ViewController para presentar esto o hay una manera de llamarlo desde un GameScene.

Encontré ESTA respuesta, pero es Objective-C.

Existen muchas maneras de manejar esta situación, no recomiendo la respuesta de Jozemite Apps, ya que esto causará problemas en las aplicaciones con más de 1 controller de vista (desea presentar la alerta en el controller de vista actual, no en la raíz)

Mi forma preferida de hacerlo es a través de la delegación. Lo que hay que hacer es crear un protocolo para manejar los posts:

 import Foundation protocol ViewControllerDelegate { func sendMessage(message:String); } 

En su controller de vista:

 class ViewController : UIViewController, ViewControllerDelegate { ... func sendMessage(message:String) { //do alert view code here } //in the view controllers view did load event func viewDidLoad() { var view = self.view as! GameSceneView view.delegate = self } 

En su código de vista:

  var delegate : ViewControllerDelegate 

Finalmente en la escena del juego donde quieres presentar:

 self.view.delegate?.sendMessage(message) 

De esta manera, permite un acceso limitado al VC, y se puede modificar con más opciones cuando sea necesario.

Otra forma es configurar un sistema de notificación y usar NSNotificationCenter para pasar un post de la escena al VC actual y hacer que envíe un post;

en ViewController

 func viewDidLoad() { NSNotificationCenter.defaultCenter().addObserver(self,selector:"AlertMessage:",name:"AlertMessage",object:nil); } func AlertMessage(notification:NSNotification) { if(let userInfo = notification.userInfo) { let message = userInfo["message"] ....//do alert view call here } } 

En el código de escena del juego:

 ...at the spot you want to send a message let userInfo = ["message":message]; NSNotificationCenter.defaultCenter.postNotificationNamed("AlertMessage",object:nil,userInfo:userInfo) 

Otro enfoque es save el puntero del controller de vista en la vista de escena del juego:

 //in Game Scene View code var viewController : UIViewController; //in the view controllers view did load event func viewDidLoad() { var view = self.view as! GameSceneView view.viewController = self } //finally in game scene where you want to present let myAlert: UIAlertController = UIAlertController(title: "Alert!", message: "Oh! Fancy", prefernetworkingStyle: .Alert) myAlert.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil)) self.view.viewController.presentViewController(myAlert, animated: true, completion: nil) 

Sin embargo, otra forma es hacer que su controller de vista sea global.

En el código de controller de vista: private var _instance: UIViewController

 class ViewController : UIViewController { class var instance { get { return _instance; } } func viewDidLoad() { _instance = self; } } 

Entonces simplemente llama

 ViewController.instance!. 

siempre que necesite acceder a su controller de vista.

Cada uno de estos methods tiene fortalezas y debilidades, así que elige cualquier forma que sea mejor para ti.

Intenta usar esto. Trabajo en SpriteKit y utilicé este código para mis posts de compra de aplicaciones en mi juego, Chomp'd.

 self.view?.window?.rootViewController?.presentViewController(myAlert, animated: true, completion: nil) 

La respuesta de @ Knight0fDragon es buena, pero creo que es un poco larga. Pondré aquí otra solución usando Podfile of Cocoapoad para los recién llegados (otros chicos tienen el mismo problema).

  1. primero debes instalar cocoapod e iniciarlo para tu proyecto (muy fácil de hacer; consulta algún video de YouTube o este enlace .

  2. en su Podfile obtenido, copie y pegue esto: pod 'SIAlertView' . Es "Un reemploop de UIAlertView con syntax de bloque y styles de transición elegantes". (Más detalles aquí . Dé crédito a las bibliotecas de los autores que está utilizando.

  3. Finalmente, en su file GameScene.swift agregue lo siguiente después de la import o después del soporte de cierre de la class GameScene

     private extension GameScene { func showPauseAlert() { let alertView = SIAlertView(title: "Edess!!", andMessage: "Congratulations! test testing bla bla bla") alertView.addButtonWithTitle("OK", type: .Default) { (alertView) -> Void in print("ok was pushed") } alertView.show() } } 

Puede agregar muchos botones con título si lo desea y hacer la acción que desee. Aquí acabo de imprimir "Ok fue presionado".

Los enlaces mencionados más este me ayudaron a entender y trabajar con este UIAlertView fácilmente en mi juego de múltiples niveles, para mostrar la alerta en el button "Pausa" del juego.