react notification apple push-notification apple-push-notifications appdelegate

push-notification - apple - push notifications ios swift 4



Controlar qué controlador de vista se carga después de recibir una notificación de inserción en SWIFT (6)

Además de la respuesta de @NickCatib, para averiguar si recibió una notificación mientras su aplicación se está ejecutando y, de ser así, en primer plano o en segundo plano debe usar este método en su AppDelegate:

func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) { // You can determine your application state by if UIApplication.sharedApplication().applicationState == UIApplicationState.Active { // Do something you want when the app is active } else { // Do something else when your app is in the background } }

Una vez que recibo una notificación de inserción y deslice para abrirla, solo abre mi aplicación y no el VC que quiero.

Entonces mi pregunta es ¿cómo puedo cargar el VC que quiero? Sé que si la aplicación está abierta movería el VC a otro dentro de didReceiveRemoteNotification pero, ¿cómo lo hago si la aplicación no está abierta? ¿O si está en modo fondo?

También tengo DOS notificaciones push diferentes, por lo tanto, necesito mover UNO DE DOS VCs diferentes. ¿Cómo puedo saber la diferencia entre las diferentes notificaciones push?

Gracias.


Cuando ejecutas tu aplicación, estás llamando a applicationDidLaunchWithOptions:

UIApplication.sharedApplication().registerUserNotificationSettings ( UIUserNotificationSettings(forTypes: (UIUserNotificationType.Alert | UIUserNotificationType.Badge | UIUserNotificationType.Sound), categories: nil)) if( launchOptions != nil){ var notificationDict: AnyObject? = launchOptions?[UIApplicationLaunchOptionsRemoteNotificationKey] if(notificationDict != nil){ handleNotification(notificationDict! as! [NSObject : AnyObject]) } }

Aquí, tienes handleNotification, que es básicamente mi función personalizada donde extraigo datos de la notificación y uso esa información para mostrar el controlador correspondiente.

Aquí hay un ejemplo de eso:

let notificationType = userInfo["aps"]!["alert"]!!["some-key-I-Need"]! as! String var storyboard = UIStoryboard(name: "Main", bundle: nil) let mainViewController = storyboard.instantiateInitialViewController() as! MyViewController self.window?.rootViewController = mainViewController


Encontré que todas las respuestas anteriores son muy útiles. Sin embargo, el más votado no funcionó para mí cuando la aplicación está desactivada. Más tarde, intenté implementar las respuestas de @NickCatib y @thefredelement combinadas y generaron un error al ejecutar storyboard.instantiateInitialViewController () - "No se pudo convertir el valor del tipo ''UINavigationController''". Descubrí que esto sucedió porque tengo un archivo de guión gráfico con NavController como rootViewController. Para resolver este problema, creé un nuevo controlador de navegación, y funcionó con un problema: perdí la navegación correcta para la aplicación y la vista ni siquiera mostraba el botón Atrás. La respuesta a mis problemas fue usar las respuestas de @NickCatib y @thefredelement, pero crear una instancia de la vista usando un identificador y empujarla, usando el rootViewController como un UINavigationController, como se muestra a continuación.

let rootViewController = self.window?.rootViewController as! UINavigationController let storyboard = UIStoryboard(name: "Main", bundle: nil) let mvc = storyboard.instantiateViewControllerWithIdentifier("MyViewController") as! MyViewController rootViewController.pushViewController(mvc, animated: true)

Esto funcionó bien para mí, y no perdí las propiedades de navegación correctas para la aplicación.


La respuesta de Swift Rabbit es la mejor.

Me gustaría agregar que aún falta cuando la aplicación se cierra al estado activo.

Puede agregar en AppDelegate, dentro de didFinishedLaunchingWithOptions:

if let notification = launchOptions?[.remoteNotification] as? [AnyHashable : Any] { notificationsUserInfo = notification as [AnyHashable : Any] serveNotifications = true }

Puede crear una variable global o un valor predeterminado del usuario con el valor de la notificación, y usar una marca para permitir que el resto de la aplicación reciba una notificación.

Una vez que el mainViewController esté visible, puede realizar acciones para procesar las notificaciones.

override func viewDidAppear(_ animated: Bool) { if serveNotifications { notificationManager.sharedInstance.processNotification(userInfo: notificationsUserInfo) serveNotifications = false } }

Cuídate.


Actualizado para Swift 3.0

Como se dijo, desea registrarse para notificaciones remotas en applicationDidLaunchWithOptions:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { let pushSettings = UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil) UIApplication.shared.registerUserNotificationSettings(pushSettings) UIApplication.shared.registerForRemoteNotifications() }

No hay forma de saber en qué viewController estarás cuando vuelvas de la pantalla de bloqueo / Fondo. Lo que hago es enviar una notificación desde el appDelegate. Cuando recibe una RemoteNotification, didReceiveRemoteNotification en el appDelegate se llama.

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) { let notif = JSON(userInfo) // SwiftyJSON required

Dependiendo de lo que contenga su notificación, primero debe asegurarse de que no sea nulo y luego llamar a una notificación que será capturada por los viewControllers que deben capturar esta notificación. Podría verse así, solo tómalo como ejemplo:

if notif["callback"]["type"] != nil{ NotificationCenter.default.post(name: Notification.Name(rawValue: "myNotif"), object: nil) // This is where you read your JSON to know what kind of notification you received, for example : }

Por ejemplo, si recibe una notificación de mensaje y ya no ha iniciado sesión porque el token ha caducado, la notificación nunca se detectará en el controlador de vista, ya que nunca se verá.

Ahora para la parte donde se captura la notificación en el controlador de vista. En la vista, aparecerá:

override func viewWillAppear(_ animated: Bool) { NotificationCenter.default.addObserver(self, selector: #selector(self.catchIt), name: NSNotification.Name(rawValue: "myNotif"), object: nil) }

Ahora que agregó este observador, cada vez que se llame a una notificación en este controlador, también se llamará la función catchIt. Tendrá que implementarlo en cada controlador de vista que desee implementar una acción específica.

func catchIt(_ userInfo: Notification){ if userInfo.userInfo?["userInfo"] != nil{ let prefs: UserDefaults = UserDefaults.standard prefs.removeObject(forKey: "startUpNotif") prefs.synchronize() let storyboard = UIStoryboard(name: "Main", bundle: nil) let vc: RedirectAppInactiveVC = storyboard.instantiateViewController(withIdentifier: "RedirectAppInactiveVC") as! RedirectAppInactiveVC self.navigationController?.pushViewController(vc, animated: true) } else{ let storyboard = UIStoryboard(name: "Main", bundle: nil) let vc: RedirectAppActiveVC = storyboard.instantiateViewController(withIdentifier: "RedirectAppActiveVC") as! RedirectAppActiveVC self.navigationController?.pushViewController(vc, animated: true) } }

No se olvide de cancelar la suscripción de las notificaciones cuando abandone el controlador de vista; de lo contrario, viewController, si aún está en la pila, detectará la notificación y la ejecutará (puede que desee hacerlo, pero es más seguro saber en qué está ingresando). ). Así que sugiero anular la suscripción en la vista.

override func viewWillDisappear(_ animated: Bool) { NotificationCenter.default.removeObserver(self) }

Haciéndolo de esta manera, cargarás el viewController que quieras. Ahora no hemos tratado todos los casos todavía. ¿Qué pasa si no ha abierto su aplicación todavía. Obviamente, no se ha cargado UIViewController, y ninguno de ellos podrá detectar la notificación. Desea saber si recibió una notificación en didFinishLaunchingWithOptions: en el appDelegate. Lo que hago es:

let prefs: UserDefaults = UserDefaults.standard if let remoteNotification = launchOptions?[UIApplicationLaunchOptionsKey.remoteNotification] as? NSDictionary { prefs.set(remoteNotification as! [AnyHashable: Any], forKey: "startUpNotif") prefs.synchronize() }

Ahora, ha establecido una preferencia que dice que la aplicación se inició usando una notificación remota. En los controladores que deberían cargarse primero en su aplicación, sugiero hacer lo siguiente en viewDidAppear:

override func viewDidAppear(animated: Bool) { let prefs:UserDefaults = UserDefaults.standard if prefs.value(forKey: "startUpNotif") != nil{ let userInfo: [AnyHashable: Any] = ["inactive": "inactive"] NotificationCenter.default.post(name: Notification.Name(rawValue: "myNotif"), object: nil, userInfo: userInfo as [AnyHashable: Any]) }

Espero eso ayude. También hice un repositorio de github para ilustrar con notificaciones locales: patrón de observador de notificaciones locales (similar a las notificaciones remotas). Se puede implementar una lógica similar utilizando el patrón raíz de las notificaciones locales del controlador de la vista raíz. Personalmente , creo que dependerá de lo que desee implementar.


Información complementaria a las respuestas anteriores.

Dependiendo de tu estado puedes cambiar tu lógica. Dentro del método didReceiveRemoteNotification :

func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {}

puedes hacer un cambio como este

let state = UIApplication.sharedApplication().applicationState switch state { case UIApplicationState.Active: case UIApplicationState.Inactive: case UIApplicationState.Background: }

y realice las acciones que desee en función del estado actual en que se encuentre la aplicación.