Otrzymuj powiadomienia push, gdy aplikacja jest na pierwszym planie iOS


191

Korzystam z usługi powiadomień wypychanych w mojej aplikacji. Gdy aplikacja jest w tle, widzę powiadomienie na ekranie powiadomień (ekran wyświetlany po przesunięciu w dół od góry urządzenia iOS). Ale jeśli aplikacja jest na pierwszym planie, metoda delegowania

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

jest wywoływany, ale powiadomienie nie jest wyświetlane na ekranie powiadomień.

Chcę wyświetlać powiadomienia na ekranie powiadomień niezależnie od tego, czy aplikacja działa w tle, czy na pierwszym planie. Jestem zmęczony szukaniem rozwiązania. Każda pomoc jest mile widziana.


35
Apple mówi : Jeśli otrzymujesz lokalne lub zdalne powiadomienia, gdy aplikacja działa na pierwszym planie, jesteś odpowiedzialny za przekazanie informacji użytkownikom w sposób specyficzny dla aplikacji.
Lauri Lehmijoki

2
Niektóre aktualne (16
azmeuk

1
nie jest obsługiwane powiadomienie wypychane na pierwszym planie dla iOS 9.3 i mniej?
Anurag Sharma

@Lauri Lehmijoki link? Nie znalazłem tego na oficjalnej stronie
Wiaczasław Gerchicow

1
Mam do czynienia z tym samym problemem jonowym ...
Sayed Mohd Ali

Odpowiedzi:


205

Aby wyświetlić komunikat banerowy, gdy aplikacja jest na pierwszym planie, użyj następującej metody.

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])
}

Musisz również zarejestrować delegata aplikacji jako delegata centrum powiadomień:

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
      ...
   }

Kiedy wywoływana jest ta metoda?
Uma Madhavi

Proszę, poprowadź mnie, że pojawia się powiadomienie z góry, gdy moja aplikacja lub tło są w tle. Od 2 tygodni pracuję z powiadomieniami push. Jestem w stanie odbierać wiadomości z serwera.
Uma Madhavi

@UmaMadhavi Czy możesz otrzymywać powiadomienia wypychane?
chengsam

21
Nie zapomnij ustawić delegata Centrum powiadomień jako delegata aplikacji: UNUserNotificationsCenter.current().delegate = selfw aplikacji didFinishLaunchingWithOptions
Achintya Ashok

2
Dla tych, którzy wciąż borykają się z problemami, jego UNUserNotificationCenter nie UNUserNotificationsCenter z 's' przed centrum
Raj

58

Poniższy kod będzie dla Ciebie odpowiedni:

- (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];          
    }    
}

To działa. Trochę więcej informacji o tym, co robi; gdy aplikacja jest na pierwszym planie, pojawia się natywne okno alarmowe interfejsu użytkownika z tekstem powiadomienia ( titlejest to nieco większy pogrubiony tekst, a pod nim messagemniejszy tekst. Na dole znajduje się przycisk „OK”, który należy odrzucić). Opcją applicationIconBadgeNumber ustawioną na 0 jest ukrycie liczby wyświetlanej nad ikoną aplikacji w Springboard (na przykład oznaczającej liczbę nieprzeczytanych wiadomości w aplikacji poczty). W tym przykładzie nie wiem, czy ta opcja jest nawet potrzebna.
jwinn

Czy działa to zarówno w przypadku powiadomienia UN, jak i powiadomienia UILocal?
user6631314

38

Dla każdego, kto może być zainteresowany, stworzyłem niestandardowy widok, który wygląda jak systemowy baner push na górze, ale dodaje przycisk zamykania (mały niebieski X) i opcję stuknięcia wiadomości dla niestandardowej akcji. Obsługuje także przypadek wysłania więcej niż jednego powiadomienia, zanim użytkownik zdąży odczytać / odrzucić stare (bez ograniczenia liczby osób, które mogą się gromadzić ...)

Link do GitHub: AGPushNote

Użycie jest w zasadzie on-line:

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

I tak to wygląda na iOS7 (iOS6 ma wygląd iOS6 ...)

wprowadź opis zdjęcia tutaj



Fajnie, to się przyda.
无 夜 之 星辰

36

Cel C

wprowadź opis zdjęcia tutaj

Ponieważ iOS 10potrzebujemy zintegrować willPresentNotificationmetodę wyświetlania baneru powiadomień foreground.

Jeśli aplikacja jest w trybie pierwszego planu (aktywna)

- (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
Po prostu skopiuj kod i nie zapomnij użyć protokołu UNUserNotificationCenterDelegate.
Nik Kov,

jeśli chcę pokazać alert zamiast tego powiadomienia?
Mihir Oza

@MihirOza Chcesz UIAlertController?
Ashwini Chougale

Wiem, ale nie chcę wyskakującego powiadomienia, gdy aplikacja jest aktywna. Chcę tylko alert w mojej aplikacji.
Mihir Oza

24

Jeśli aplikacja działa na pierwszym planie, iOS nie wyświetla baneru powiadomienia / alertu. To z założenia. Ale możemy to osiągnąć, wykorzystując UILocalNotificationw następujący sposób

  • Sprawdź, czy aplikacja jest w stanie aktywnym po otrzymaniu zdalnego
    powiadomienia. Jeśli w stanie aktywnym, uruchom powiadomienie UILocalNotification.

    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];
    }

SZYBKI:

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

86
Nie sądzę, że to pomoże. Powiadomienia lokalne i zdalne są traktowane tak samo, dlatego gdy lokalne powiadomienie jest uruchamiane i jeśli aplikacja jest uruchomiona, znaczek / baner lub dźwięk nie będą wyświetlane / odtwarzane.
RPM

3

3
Jednak nie uruchamiałbym lokalnego powiadomienia, gdy nadejdzie powiadomienie push. Wprowadziłbym podobne zachowanie, jak wspomniano @ Rick77: wyświetlanie alarmu lub tostera. Wydaje mi się, że nie muszę ponownie przechodzić przez system operacyjny, aby uzyskać dostęp do czegoś, o co prosi mnie system operacyjny.
Fábio Oliveira

3
To rozwiązanie działa, ponieważ lokalne i zdalne są obsługiwane w taki sam sposób, w przypadku gdy aplikacja jest na pierwszym planie, tworzenie powiadomienia o lokalizacji, gdy nadchodzi zdalne powiadomienie, niczego nie pokazuje. Rozwiązaniem jest używanie alertu lub alertu niestandardowego
Hammer,

18
To nie działa. Z dokumentów 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

Jeśli aplikacja działa na pierwszym planie, iOS nie wyświetla baneru powiadomienia / alertu. To z założenia. Musisz napisać kod, aby poradzić sobie z sytuacją, w której aplikacja otrzymuje powiadomienie, gdy jest na pierwszym planie. Powinieneś pokazać powiadomienie w najbardziej odpowiedni sposób (na przykład dodając numer identyfikacyjny do UITabBarikony, symulując baner Centrum powiadomień itp.).


1
ale w aplikacji pocztowej na iOS już to zrobili, otrzymasz nowy baner powiadomień / alert, gdy aplikacja poczty na pierwszym planie
Ab'initio

3
@ Ab'initio Nie wiem na pewno, ale w iOS nie wszystkie aplikacje są sobie równe. Przypuszczam, że standardowa aplikacja Mail używa jakiegoś prywatnego interfejsu API, który nie jest dostępny w publicznym zestawie SDK. A może kod powiadomienia robi wyjątek z identyfikatorem aplikacji Apple Mail.
Daniel Martín

1
Co?? Zaraz mam atak harpii.
Josh

@ DanielMartín mógłby mi powiedzieć, w jaki sposób otrzymam powiadomienie w stanie pierwszoplanowym w iOS 8.0
Dilip Tiwari,

10
Pamiętaj, że ta odpowiedź jest prawdziwa tylko dla iOS 9 i niższych . Od iOS 10 Apple wprowadził nowy interfejs API do obsługi powiadomień ( UNUserNotificationCenter API). Wraz z nowym interfejsem API można teraz wyświetlać powiadomienia, jeśli aplikacja jest na pierwszym planie. Więc jeśli jesteś zdezorientowany, ponieważ różne odpowiedzi w tym pytaniu, to dlatego, że niektóre odpowiedzi są zbyt stare i opisują tylko zachowanie dla iOS 9 i wcześniejszych, podczas gdy inne nie biorą pod uwagę, że UNUserNotificationCenter są dostępne tylko z iOS 10.
tomacco

12

Xcode 10 Swift 4.2

Aby wyświetlić powiadomienie push, gdy aplikacja jest na pierwszym planie -

Krok 1: Dodaj delegowanego UNUserNotificationCenterDelegate w klasie AppDelegate.

class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {

Krok 2: Ustaw delegata UNUserNotificationCenter

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

Krok 3: ten krok pozwoli Twojej aplikacji wyświetlać powiadomienie push, nawet jeśli aplikacja jest na pierwszym planie

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

    }

Krok 4: Ten krok jest opcjonalny . Sprawdź, czy Twoja aplikacja jest na pierwszym planie, a jeśli jest na pierwszym planie, pokaż Lokalną powiadomienie push.

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()
        }
    }

Funkcja lokalnego powiadomienia -

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
To świetny przykład potrzeby przeczytania wszystkich odpowiedzi w wątku. Wcześniejsze wątki wspominały o metodzie, niż o delegacie, a na koniec o wszystkich trzech krokach, które należy wykonać. DZIĘKUJĘ Prashant za pełną odpowiedź!
user3069232

Dobrze wiedzieć, że ci pomogło. Szczęśliwego kodowania
Prashant Gaikwad

10

Zgodnie z dokumentacją firmy Apple Tak, możesz wyświetlać powiadomienia, gdy aplikacja jest uruchomionawprowadź opis zdjęcia tutaj


gdzie mogę napisać tę funkcję albo w aplikacji delegowanej, albo w określonej klasie?
iOS Developer

co jeśli chcę napisać ten metd w widoku załadował?
iOS Developer

możesz napisać gdziekolwiek, ale warunek jest zgodny z UNUserNotificationCenterDelegateprotokołem
SPatel

nie możesz pisaćviewDidLoad
SPatel

1
Proponuję rozszerzyć AppDelegateextension AppDelegate: UNUserNotificationCenterDelegate
SPatel

9

Możesz utworzyć własne powiadomienie, które naśladuje alert banerowy.

Jednym ze sposobów jest utworzenie niestandardowego uiviewu, który wygląda jak baner i może animować i reagować na dotyk. Mając to na uwadze, możesz tworzyć jeszcze lepsze banery o jeszcze większej funkcjonalności.

Możesz też poszukać interfejsu API, który zrobi to za Ciebie, i dodaj je jako pliki podfile do swojego projektu.

Oto kilka, których użyłem:

https://github.com/terryworona/TWMessageBarManager

https://github.com/toursprung/TSMessages


1
Chociaż ten link może odpowiedzieć na pytanie, lepiej dołączyć tutaj istotne części odpowiedzi i podać link w celach informacyjnych. Odpowiedzi zawierające tylko łącze mogą stać się nieprawidłowe, jeśli połączona strona ulegnie zmianie.
Robert

1
TWMessageBarManagermoże być łatwo wywoływany i używany przez samą appdelegate, ponieważ używa wzorca projektowego singleton. Dzięki za linki.
Jay Mayu,

8

Oto kod do otrzymywania powiadomień push, gdy aplikacja jest w stanie aktywnym (na pierwszym planie lub otwarta). Dokumentacja UNUserNotificationCenter

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

Aby uzyskać dostęp do informacji o użytkowniku powiadomienia, użyj kodu: notification.request.content.userInfo


gdzie napisać tę funkcję w widoku załadowano? lub w widoku klasy kontrolera?
iOS Developer

co jeśli mogę wywołać go w funkcji jako funkcja zagnieżdżona, czy byłby nazwany> ??
iOS Developer

1
umieść to w klasie AppDelegate. Nie musisz wywoływać tej funkcji.
Milan Jayawardane,

4

Dodanie linii uzupełniającej metody obsługi do metody delegowania rozwiązało dla mnie ten sam problem:

//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

Dla szybkiego 5 parsowania słownika 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)")
                            }
                        }
                    }
                }
            }
        }

Aby pobrać widok z góryController, na którym pokazujemy 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
    }
}

guardStwierdzenie jest twoim przyjacielem :-)
Nicolas Miari

2

W swojej aplikacji deleguj użyj poniższego kodu

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])
    }
}

0

Jak wspomniano powyżej, należy użyć UserNotification.frameworkdo osiągnięcia tego. Ale dla moich celów i tak muszę to pokazać w aplikacji i chciałem mieć iOS 11styl, więc stworzyłem widok małego pomocnika, być może przydałby się komuś.

Widok powiadomień push GitHub iOS 11 .


0

Najlepszym sposobem na to jest dodanie UNUserNotificationCenterDelegatew AppDelegateza pomocąextension AppDelegate: UNUserNotificationCenterDelegate tego rozszerzenia informuje aplikację, aby móc otrzymać powiadomienie, gdy w użyciu

I zaimplementuj tę metodę

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

Ta metoda zostanie wywołana na uczestniku tylko, jeśli aplikacja jest na pierwszym planie .

Ostateczne wdrożenie:

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

Aby zadzwonić, musisz ustawić delegata w AppDelegate w didFinishLaunchingWithOptionsdodać tę linię

UNUserNotificationCenter.current().delegate = self

Możesz modyfikować

completionHandler(.alert) 

z

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

0

Dla Swift 5

1) Potwierdź delegata do AppDelegate za pomocą UNUserNotificationCenterDelegate

2) UNUserNotificationCenter.current().delegate = selfwdidFinishLaunch

3) Zastosuj poniższą metodę w AppDelegate.

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

Otóż ​​to!


-2

Jak powiedział @Danial Martine, iOS nie wyświetla baneru powiadomienia / alertu. To z założenia. Ale jeśli naprawdę trzeba to zrobić, istnieje jeden sposób. Ja również to osiągnąłem.

1. Pobierz pracę parsowania ramki z Parse FrameWork

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

3. Dodaj następujący kod do metody didReceiveRemoteNotification

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

PFPush zajmie się obsługą zdalnego powiadomienia. Jeśli aplikacja jest na pierwszym planie, wyświetla alert, w przeciwnym razie wyświetla powiadomienie u góry.


alarm? masz na myśli widok alertu?
iphondroid

1
ale jak uzyskać oddzwonienie w celu wykonania akcji przycisku ostrzegania
Charlie

-2

Jeśli aplikacja znajduje się na pierwszym planie, oznacza to, że obecnie używasz tej samej aplikacji. Nie ma więc potrzeby, aby ogólnie wyświetlać powiadomienie.

Ale nadal, jeśli chcesz pokazać powiadomienie w takim przypadku, musisz utworzyć niestandardowy widok alertu lub widok niestandardowy, np. Toast lub coś innego, aby pokazać użytkownikowi, że masz powiadomienie.

Możesz również wyświetlić znaczek na górze, jeśli masz taką funkcję w swojej aplikacji.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.