Ricevi notifiche push mentre l'app è in primo piano iOS


192

Sto utilizzando il servizio di notifica push nella mia app. Quando l'app è in background sono in grado di vedere le notifiche nella schermata di notifica (schermata mostrata quando scorri verso il basso dalla parte superiore del dispositivo iOS). Ma se l'applicazione è in primo piano il metodo delegato

- (void)application:(UIApplication*)application didReceiveRemoteNotification:(NSDictionary*)userInfo

viene chiamato ma la notifica non viene visualizzata nella schermata di notifica.

Voglio mostrare la notifica sulla schermata di notifica indipendentemente dal fatto che l'app sia in background o in primo piano. Sono stanco di cercare una soluzione. Qualsiasi aiuto è molto apprezzato.


35
Apple afferma : se ricevi notifiche locali o remote mentre l'app è in esecuzione in primo piano, sei responsabile del passaggio delle informazioni ai tuoi utenti in un modo specifico per l'app.
Lauri Lehmijoki,

2
Alcuni link Apple aggiornati (ott "16): qui , qua e
azmeuk,

1
non è il supporto in primo piano della notifica push per iOS 9.3 e meno?
Anurag Sharma,

@Lauri Lehmijoki link? Non l'ho trovato sul sito ufficiale
Vyachaslav Gerchicov il

1
Sto affrontando lo stesso problema in ionico ...
Ha detto Mohd Ali il

Risposte:


208

Per visualizzare il messaggio banner mentre l'app è in primo piano, utilizzare il seguente metodo.

iOS 10, Swift 3/4 :

// This method will be called when app received push notifications in foreground
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) 
{
    completionHandler([.alert, .badge, .sound])
}

iOS 10, Swift 2.3 :

@available(iOS 10.0, *)
func userNotificationCenter(center: UNUserNotificationCenter, willPresentNotification notification: UNNotification, withCompletionHandler completionHandler: (UNNotificationPresentationOptions) -> Void)
{
    //Handle the notification
    completionHandler(
       [UNNotificationPresentationOptions.Alert,
        UNNotificationPresentationOptions.Sound,
        UNNotificationPresentationOptions.Badge])
}

È inoltre necessario registrare il delegato dell'app come delegato per il centro notifiche:

import UserNotifications

// snip!

class AppDelegate : UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate

// snip!

   func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

      // set the delegate in didFinishLaunchingWithOptions
      UNUserNotificationCenter.current().delegate = self
      ...
   }

Quando viene chiamato questo metodo?
Uma Madhavi,

Per favore, guidami, mi viene visualizzato il messaggio di visualizzazione dall'alto quando la mia app in background o in primo piano. Da 2 settimane sto lavorando con le notifiche push. Sono in grado di ricevere messaggi dal server.
Uma Madhavi,

@UmaMadhavi Puoi ricevere notifiche push?
chengsam,

21
Non dimenticare di impostare il delegato del Centro notifiche come delegato dell'app: UNUserNotificationsCenter.current().delegate = selfnell'applicazione didFinishLaunchingWithOptions
Achintya Ashok

2
Per coloro che ancora lottano, il suo UNUserNotificationCenter non UNUserNotificationsCenter con 's' prima del centro
Raj

58

Di seguito il codice funzionerà per te:

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo  {
    application.applicationIconBadgeNumber = 0;             
    //self.textView.text = [userInfo description];
    // We can determine whether an application is launched as a result of the user tapping the action
    // button or whether the notification was delivered to the already-running application by examining
    // the application state.

    if (application.applicationState == UIApplicationStateActive) {                
        // Nothing to do if applicationState is Inactive, the iOS already displayed an alert view.                
        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Did receive a Remote Notification" message:[NSString stringWithFormat:@"Your App name received this notification while it was running:\n%@",[[userInfo objectForKey:@"aps"] objectForKey:@"alert"]]delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
        [alertView show];          
    }    
}

Questo funziona Un po 'più di informazioni su ciò che fa; quando l'applicazione è in primo piano, viene visualizzata una finestra di avviso dell'interfaccia utente nativa con al suo interno il testo della notifica (si titletratta di un testo in grassetto leggermente più grande e messagesotto c'è un testo più piccolo. Un pulsante 'OK' per chiudere è in fondo). L'opzione applicationIconBadgeNumber impostata su 0 serve a nascondere il numero che appare in cima all'icona dell'app in Springboard (ad esempio il numero di messaggi non letti in un'app di posta). In questo esempio, non so se tale opzione sia necessaria.
Jwinn,

Funziona sia con UNnotification sia con UILocalNotification?
user6631314

38

Per chiunque potrebbe essere interessato, ho finito per creare una vista personalizzata che assomiglia al banner push di sistema in alto ma aggiunge un pulsante di chiusura (piccola X blu) e un'opzione per toccare il messaggio per un'azione personalizzata. Supporta anche il caso in cui più di una notifica sia arrivata prima che l'utente avesse il tempo di leggere / eliminare quelle vecchie (senza limite a quante possono accumularsi ...)

Link a GitHub: AGPushNote

L'utilizzo è sostanzialmente on-line:

[AGPushNoteView showWithNotificationMessage:@"John Doe sent you a message!"];

E sembra così su iOS7 (iOS6 ha un aspetto iOS6 ...)

inserisci qui la descrizione dell'immagine


1
Anche ora reinventato in Swift: github.com/charliewilliams/CWNotificationBanner (da me)
buildsuceded

Bello , questo sarà utile.
无 夜 之 星辰

35

Obiettivo C

inserisci qui la descrizione dell'immagine

Perché iOS 10abbiamo bisogno del willPresentNotificationmetodo integrato per mostrare il banner di notifica in foreground.

Se l'app in modalità primo piano (attiva)

- (void)userNotificationCenter:(UNUserNotificationCenter* )center willPresentNotification:(UNNotification* )notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler {
    NSLog( @“Here handle push notification in foreground" ); 
    //For notification Banner - when app in foreground

    completionHandler(UNNotificationPresentationOptionAlert);

    // Print Notification info
    NSLog(@"Userinfo %@",notification.request.content.userInfo);
}

1
Basta copiare il codice e non dimenticare di utilizzare il protocollo UNUserNotificationCenterDelegate.
Nik Kov,

se voglio mostrare un avviso invece di questa notifica, allora?
Mihir Oza,

@MihirOza Vuoi UIAlertController?
Ashwini Chougale,

Lo so ma non voglio un popup di notifica quando l'app è attiva. Voglio solo avvisi nella mia app.
Mihir Oza,

ho provato la tua funzione ma non riesco ancora a mettere in primo piano
Khaled Boussoffara

25

Se l'applicazione è in esecuzione in primo piano, iOS non mostrerà un banner / avviso di notifica. Questo è di progettazione. Ma possiamo raggiungerlo usando UILocalNotificationcome segue

  • Controllare se l'applicazione è in stato attivo alla ricezione di una
    notifica remota . Se nello stato attivo attiva una notifica UILocal.

    if (application.applicationState == UIApplicationStateActive ) {
    
        UILocalNotification *localNotification = [[UILocalNotification alloc] init];
        localNotification.userInfo = userInfo;
        localNotification.soundName = UILocalNotificationDefaultSoundName;
        localNotification.alertBody = message;
        localNotification.fireDate = [NSDate date];
        [[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
    }

SWIFT:

if application.applicationState == .active {
    var localNotification = UILocalNotification()
    localNotification.userInfo = userInfo
    localNotification.soundName = UILocalNotificationDefaultSoundName
    localNotification.alertBody = message
    localNotification.fireDate = Date()
    UIApplication.shared.scheduleLocalNotification(localNotification)
}

86
Non penso che questo possa aiutare. Le notifiche locali e remote vengono trattate allo stesso modo e di conseguenza quando questa notifica locale si attiva e se l'app è in esecuzione, il badge / banner o il suono non verranno visualizzati / riprodotti.
RPM

3
Lascerà anche una voce nel Centro di notifica iOS
Ab'initio

3
Tuttavia non lancerei una notifica locale quando arriva una notifica push. Avrei lanciato un comportamento simile invece come citato da @ Rick77: mostrando un avviso o un tostapane. Immagino di non dover ricorrere nuovamente al sistema operativo per qualcosa che il sistema operativo mi sta chiedendo di gestire.
Fábio Oliveira,

3
Questa soluzione funziona, poiché locale e remoto sono gestiti allo stesso modo, quando l'app è in primo piano, la creazione di una notifica di posizione quando arriva la notifica remota non mostrerà nulla. L'uso di un avviso o un avviso personalizzato è la soluzione
Hammer,

19
Questo in realtà non funziona. Dai documenti di UILocalNotification:If the app is foremost and visible when the system delivers the notification, the app delegate’s application:didReceiveLocalNotification: is called to process the notification. Use the information in the provided UILocalNotification object to decide what action to take. The system does not display any alerts, badge the app’s icon, or play any sounds when the app is already frontmost.
Chris Morse,

15

Se l'applicazione è in esecuzione in primo piano, iOS non mostrerà un banner / avviso di notifica. Questo è di progettazione. Devi scrivere un codice per gestire la situazione della tua app che riceve una notifica mentre è in primo piano. È necessario mostrare la notifica nel modo più appropriato (ad esempio, aggiungendo un numero di badge a UITabBarun'icona, simulando un banner del Centro notifiche, ecc.).


1
ma nell'applicazione di posta iOS lo hanno fatto, riceverai un nuovo banner / avviso di notifica mentre l'app di posta in primo piano
Ab'initio

3
@ Ab'initio non lo so per certo, ma in iOS tutte le applicazioni non sono create uguali. Suppongo che l'app di posta di serie stia utilizzando un tipo di API privata che non è disponibile nell'SDK pubblico. O forse il codice di notifica sta facendo un'eccezione con l'id dell'app Mail di Apple.
Daniel Martín

1
Che cosa?? Sto per subire un attacco di rabbia.
Josh

@ DanielMartín potresti dirmi come riceverò una notifica in primo piano in iOS 8.0
Dilip Tiwari

10
Tieni presente che questa risposta è vera solo per iOS 9 e versioni precedenti . Da iOS 10, Apple ha introdotto una nuova API per gestire le notifiche ( UNUserNotificationCenter API). Insieme alla nuova API, ora è possibile mostrare le notifiche se l'applicazione è in primo piano. Quindi, se sei confuso perché le diverse risposte in questa domanda, è perché alcune delle risposte sono troppo vecchie e descrivono solo il comportamento per iOS 9 e precedenti, mentre le altre non tengono conto del fatto che UNUserNotificationCenter è disponibile solo da iOS 10.
tomacco

13

Xcode 10 Swift 4.2

Per mostrare la notifica push quando l'app è in primo piano -

Passaggio 1: aggiungere delegato UNUserNotificationCenterDelegate nella classe AppDelegate.

class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {

Passo 2 : impostare il delegato UNUserNotificationCenter

let notificationCenter = UNUserNotificationCenter.current()
notificationCenter.delegate = self

Passaggio 3: questo passaggio consentirà all'app di mostrare le notifiche push anche quando l'app è in primo piano

func userNotificationCenter(_ center: UNUserNotificationCenter,
                                willPresent notification: UNNotification,
                                withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        completionHandler([.alert, .sound])

    }

Passaggio 4: questo passaggio è facoltativo . Controlla se la tua app è in primo piano e se è in primo piano, quindi mostra Local PushNotification.

func application(_ application: UIApplication,didReceiveRemoteNotification userInfo: [AnyHashable: Any],fetchCompletionHandler completionHandler:@escaping (UIBackgroundFetchResult) -> Void) {

        let state : UIApplicationState = application.applicationState
        if (state == .inactive || state == .background) {
            // go to screen relevant to Notification content
            print("background")
        } else {
            // App is in UIApplicationStateActive (running in foreground)
            print("foreground")
            showLocalNotification()
        }
    }

Funzione di notifica locale -

fileprivate func showLocalNotification() {

        //creating the notification content
        let content = UNMutableNotificationContent()

        //adding title, subtitle, body and badge
        content.title = "App Update"
        //content.subtitle = "local notification"
        content.body = "New version of app update is available."
        //content.badge = 1
        content.sound = UNNotificationSound.default()

        //getting the notification trigger
        //it will be called after 5 seconds
        let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 1, repeats: false)

        //getting the notification request
        let request = UNNotificationRequest(identifier: "SimplifiedIOSNotification", content: content, trigger: trigger)

        //adding the notification to notification center
        notificationCenter.add(request, withCompletionHandler: nil)
    }

1
Questo è un ottimo esempio della necessità di leggere tutte le risposte a una discussione. I thread precedenti menzionano il metodo, rispetto al delegato e infine questo tutti e tre i passaggi che è necessario eseguire. GRAZIE Prashant per una risposta completa!
user3069232

Buono a sapersi che ti ha aiutato. Buona programmazione
Prashant Gaikwad,

11

Secondo la documentazione di Apple , Sì, è possibile visualizzare le notifiche mentre l'app è in esecuzioneinserisci qui la descrizione dell'immagine


dove posso scrivere quella funzione o in delegato app o in una classe specifica ??
Sviluppatore iOS

cosa succede se voglio scrivere quel methd in vista caricato ??
Sviluppatore iOS

puoi scrivere ovunque ma a condizione che sia conforme al UNUserNotificationCenterDelegateprotocollo
SPatel

non puoi scrivereviewDidLoad
SPatel

1
ti suggerisco di estendere AppDelegateextension AppDelegate: UNUserNotificationCenterDelegate
SPatel

9

Puoi creare la tua notifica che imita l'avviso banner.

Un modo è creare un'Uiview personalizzata che assomigli al banner e possa animare e rispondere ai tocchi. Con questo in mente puoi creare banner ancora migliori con ancora più funzionalità.

Oppure puoi cercare un'API che lo fa per te e aggiungerli come file pod al tuo progetto.

Ecco un paio che ho usato:

https://github.com/terryworona/TWMessageBarManager

https://github.com/toursprung/TSMessages


1
Sebbene questo collegamento possa rispondere alla domanda, è meglio includere qui le parti essenziali della risposta e fornire il collegamento come riferimento. Le risposte di solo collegamento possono diventare non valide se la pagina collegata cambia.
Robert,

1
TWMessageBarManagerpuò essere facilmente richiamato e utilizzato tramite appdelegate stesso in quanto utilizza il modello di progettazione singleton. Grazie per i collegamenti.
Jay Mayu,

8

Ecco il codice per ricevere la notifica push quando l'app è in stato attivo (in primo piano o aperto). Documentazione UNUserNotificationCenter

@available(iOS 10.0, *)
func userNotificationCenter(center: UNUserNotificationCenter, willPresentNotification notification: UNNotification, withCompletionHandler completionHandler: (UNNotificationPresentationOptions) -> Void)
{
     completionHandler([UNNotificationPresentationOptions.Alert,UNNotificationPresentationOptions.Sound,UNNotificationPresentationOptions.Badge])
}

Se è necessario accedere all'utenteInfo della notifica utilizzare il codice: notification.request.content.userInfo


dove scrivere questa funzione in vista caricata? o in vista classe controller?
Sviluppatore iOS

cosa succede se posso chiamarlo in una funzione come una funzione nidificata sarebbe chiamato> ??
Sviluppatore iOS

1
mettilo nella classe AppDelegate. Non è necessario chiamare questa funzione.
Milan Jayawardane,

4

L'aggiunta di tale linea di completamento al metodo delegato ha risolto lo stesso problema per me:

//Called when a notification is delivered to a foreground app.
@available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {

completionHandler([.alert, .badge, .sound])
} 

3

Per swift 5 analizzare il dizionario PushNotification

    func application(_ application: UIApplication, didReceiveRemoteNotification data: [AnyHashable : Any]) {
            if application.applicationState == .active {
                if let aps1 = data["aps"] as? NSDictionary {
                    if let dict = aps1["alert"] as? NSDictionary {
                        if let strTitle = dict["title"] as? String , let strBody = dict["body"] as? String {
                            if let topVC = UIApplication.getTopViewController() {
                                //Apply your own logic as per requirement
                                print("strTitle ::\(strTitle) , strBody :: \(strBody)")
                            }
                        }
                    }
                }
            }
        }

Per recuperare la vista dall'altoController su cui mostriamo topBanner

extension UIApplication {

    class func getTopViewController(base: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController? {

        if let nav = base as? UINavigationController {
            return getTopViewController(base: nav.visibleViewController)

        } else if let tab = base as? UITabBarController, let selected = tab.selectedViewController {
            return getTopViewController(base: selected)

        } else if let presented = base?.presentedViewController {
            return getTopViewController(base: presented)
        }
        return base
    }
}

La guarddichiarazione è tua amica :-)
Nicolas Miari il

2

Nella tua app delegato usa il codice qui sotto

import UIKit
import UserNotifications
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {
 var currentToken: String?
 var window: UIWindow?
 func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        application.registerForRemoteNotifications()
        let center = UNUserNotificationCenter.current()
        center.requestAuthorization(options: [.alert, .sound, .badge]) { (granted, error) in

            // Enable or disable features based on authorization.
            if granted == true
            {
                print("Allow")
                UIApplication.shared.registerForRemoteNotifications()
            }
            else
            {
                print("Don't Allow")
            }
        }
        UNUserNotificationCenter.current().delegate = self

        return true
    }
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data){
        let tokenParts = deviceToken.map { data -> String in
            return String(format: "%02.2hhx", data)
        }
        let token = tokenParts.joined()
        currentToken = token  //get device token to delegate variable

    }
 public class var shared: AppDelegate {
        return UIApplication.shared.delegate as! AppDelegate
    }
 func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
         completionHandler([.alert, .badge, .sound])
    }
}

1

Per Swift 5

1) Confermare il delegato all'AppDelegate con UNUserNotificationCenterDelegate

2) UNUserNotificationCenter.current().delegate = selfindidFinishLaunch

3) Implementare il metodo seguente in AppDelegate.

func userNotificationCenter(_ center: UNUserNotificationCenter,
                                willPresent notification: UNNotification,
                                withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
     print("Push notification received in foreground.")
     completionHandler([.alert, .sound, .badge])
}

Questo è tutto!


0

Come accennato in precedenza, è necessario utilizzare UserNotification.frameworkper raggiungere questo obiettivo. Ma per i miei scopi devo comunque mostrarlo in app e volevo averloiOS 11 stile, quindi ho creato una piccola vista di supporto, forse sarebbe utile per qualcuno.

GitHub iOS 11 Visualizzazione notifica push .


0

Approccio migliore per questo è di aggiungere UNUserNotificationCenterDelegatein AppDelegateutilizzandoextension AppDelegate: UNUserNotificationCenterDelegate Tale proroga racconta l'app per essere in grado di avere la notifica quando è in uso

E implementare questo metodo

func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        completionHandler(.alert)
    }

Questo metodo verrà chiamato sul delegato solo se l'applicazione è in primo piano .

Quindi l'implementazione finale:

extension AppDelegate: UNUserNotificationCenterDelegate {
    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        completionHandler(.alert)
    }
}

E per chiamare questo è necessario impostare il delegato in AppDelegate per didFinishLaunchingWithOptionsaggiungere questa riga

UNUserNotificationCenter.current().delegate = self

Puoi modificare

completionHandler(.alert) 

con

completionHandler([.alert, .badge, .sound]))

-2

Se l'applicazione è in primo piano, significa che stai utilizzando la stessa app. Quindi non è necessario mostrare la notifica in alto in generale.

Tuttavia, se vuoi mostrare la notifica in quel caso, devi creare la tua Visualizzazione avvisi personalizzata o Visualizzazione personalizzata come Toast o qualcos'altro per mostrare all'utente che hai ricevuto una notifica.

Puoi anche mostrare un badge in alto se hai questo tipo di funzionalità nella tua app.


-3

Come ha detto @Danial Martine, iOS non mostrerà un banner / avviso di notifica. Questo è di progettazione. Ma se davvero devi farlo, allora c'è un modo. Ho raggiunto questo obiettivo allo stesso modo.

1. Scaricare il lavoro del frame di analisi da Parse FrameWork

2.Import #import <Parse/Parse.h>

3.Aggiungi il seguente codice al tuo metodo didReceiveRemoteNotification

 - (void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo
{
    [PFPush handlePush:userInfo];
}

PFPush si prenderà cura di come gestire la notifica remota. Se l'app è in primo piano, questo mostra l'avviso, altrimenti mostra la notifica in alto.


mettere in guardia? intendi una vista di avviso?
iphondroid

1
ma come richiamare per le azioni dei pulsanti di avviso
Charlie
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.