Отримуйте натискання сповіщень, коли додаток на передньому плані iOS


191

Я використовую послугу push push-повідомлення у своєму додатку. Коли програма перебуває у фоновому режимі, я можу бачити сповіщення на екрані сповіщень (екран відображається, коли ми проводимо пальцем вгору від iOS пристрою). Але якщо на першому плані є делегатний метод

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

телефонує, але сповіщення не відображається на екрані сповіщень.

Я хочу показувати сповіщення на екрані сповіщень незалежно від того, додаток знаходиться у фоновому режимі чи на передньому плані. Я втомився від пошуку рішення. Будь-яка допомога дуже цінується.


35
Apple каже : Якщо ви отримуєте місцеві або віддалені сповіщення, коли ваш додаток працює на передньому плані, ви несете відповідальність за передачу інформації своїм користувачам у певному додатку.
Lauri Lehmijoki

2
Деякі актуальні посилання на яблуко (окт. 16): тут , там і там
azmeuk

1
Чи не підтримка переднього плану push-сповіщення для iOS 9.3 і менше?
Анураг Шарма

@Lauri Lehmijoki посилання? Я не знайшов цього на офіційному веб-сайті
Вячаслав Герчичов

1
Я зіткнувся з тією ж проблемою в іонному ...
Сказав Мохд Алі

Відповіді:


206

Для відображення банерного повідомлення, коли додаток на передньому плані, використовуйте наступний метод.

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

Ви також повинні зареєструвати делегата програми як делегата центру сповіщень:

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

Коли цей метод називається?
Ума Мадхаві

Підкажіть, будь ласка, я вражений, що відображати сповіщення зверху, коли фоновий додаток або передній план. З 2 тижня я працюю з push notifications. Я можу отримувати повідомлення від сервера.
Ума Мадхаві

@UmaMadhavi Чи можете ви отримувати push-повідомлення?
chengsam

21
Не забудьте встановити делегата Центру сповіщень як делегата програми: UNUserNotificationsCenter.current().delegate = selfу додатку didFinishLaunchingWithOptions
Achintya Ashok

2
Для тих, хто все ще бореться, його UNUserNotificationCenter not UNUserNotificationsCenter з 's' перед центром
Raj

58

Нижче код буде працювати для вас:

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

Це працює. Трохи більше інформації про те, що це робить; коли додаток стоїть на передньому плані, з'являється нативне поле сповіщення інтерфейсу користувача з текстом сповіщення всередині нього (текст titleтрохи більший, виділений жирним шрифтом, і messageменший текст під цим. Унизу кнопка "ОК" для відхилення). Опція applicationIconBadgeNumber встановлюється на 0 - приховати номер, який з’являється вгорі піктограми програми у Springboard (наприклад, означає кількість непрочитаних повідомлень у додатку пошти). У цьому прикладі я не знаю, чи потрібен цей варіант.
jwinn

Чи працює це як для повідомлення, так і для UILocalNotification?
користувач6631314

38

Для когось це може зацікавити, я закінчив створити спеціальний вигляд, який виглядає як банер натискання системи вгорі, але додає кнопку закриття (маленький синій X) та можливість торкнутися повідомлення для користувацьких дій. Він також підтримує випадок більше ніж одне повідомлення, що надійшло до того, як користувач встиг прочитати / відхилити старі (Без обмеження, скільки їх може накопичуватися ...)

Посилання на GitHub: AGPushNote

Використання в основному є вкладишем:

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

І це виглядає так на iOS7 (iOS6 має вигляд iOS6 ...)

введіть тут опис зображення


1
Також тепер переробили в Swift: github.com/charliewilliams/CWNotificationBanner (від мене)
buildsucced

Приємно , це буде корисно.
无 夜 之 星辰

36

Мета C

введіть тут опис зображення

Для цього iOS 10нам потрібно інтегрувати willPresentNotificationметод для показу банера сповіщень у foreground.

Якщо програма в режимі переднього плану (активна)

- (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
Просто скопіюйте код і не забудьте використовувати протокол UNUserNotificationCenterDelegate.
Нік Ков

якщо я хочу замість цього сповіщення показати попередження?
Міхір Оза

@MihirOza Ви хочете UIAlertController?
Ashwini Chougale

Я знаю, але не хочу всплывающее повідомлення, коли програма активна. Я хочу отримувати попередження лише у своєму додатку.
Міхір Оза

25

Якщо програма працює на передньому плані, iOS не відображатиме банер / сповіщення про сповіщення. Це за дизайном. Але ми можемо досягти цього, використовуючи UILocalNotificationнаступне

  • Перевірте, чи програма перебуває в активному стані після отримання віддаленого
    повідомлення. Якщо в активному стані пожежа, 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];
    }

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
Я не думаю, що це допоможе. Місцеві та віддалені сповіщення трактуються однаково, і в результаті, коли це місцеве сповіщення вимикається, і якщо програма працює, значок / банер або звук не відображатиметься / відтворюється.
RPM

3
Він також залишить запис у Центрі сповіщень iOS
Ab'initio

3
Однак я б не запускав місцеве сповіщення, коли надходить push-сповіщення. Я б запустив подібну поведінку, на зразок згаданого @ Rick77: показ попередження чи тостера. Я думаю, що мені не доведеться повторно проходити через операційну систему для чогось, що операційна система просить мене впоратися.
Фабіо Олівейра

3
Це рішення працює, оскільки локальне та віддалене управління обробляються однаково, коли, коли програма стоїть на передньому плані, створення сповіщень про місцезнаходження, коли надходить віддалене сповіщення, нічого не покаже. Використовувати сповіщення або користувацьке сповіщення - це рішення
Hammer

19
Це насправді не працює. З документів 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.
Кріс Морс

15

Якщо програма працює на передньому плані, iOS не відображатиме банер / сповіщення про сповіщення. Це за дизайном. Вам потрібно написати якийсь код, щоб розібратися з ситуацією, коли ваш додаток отримує сповіщення, коли воно стоїть на передньому плані. Ви повинні показати сповіщення найбільш підходящим чином (наприклад, додати номер значка до UITabBarзначка, імітувати банер Центру сповіщень тощо).


1
але в поштовій програмі iOS вони це зробили, ви отримаєте новий банер / сповіщення про сповіщення, коли програма для поштових повідомлень на передньому плані
Ab'initio

3
@ Ab'initio Я точно не знаю, але в iOS всі програми не створюються рівними. Я припускаю, що програма для поштових розсилок використовує якийсь приватний API, який недоступний у загальнодоступному SDK. А може, код сповіщення робить виняток із ідентифікатором програми Apple Mail.
Даніель Мартін

1
Що?? У мене ось-ось напад гарпі ярості.
Джош

@ DanielMartín міг би сказати мені, як я отримаю сповіщення про стан переднього плану в iOS 8.0
Діліп Тіварі

10
Майте на увазі, що ця відповідь справедлива лише для iOS 9 та новіших версій . Починаючи з iOS 10, Apple представила новий API для обробки сповіщень ( UNUserNotificationCenter API). Поряд з новим API тепер можна показати сповіщення, якщо додаток на першому плані. Тож якщо ви плутаєтеся через різні відповіді в цьому запитанні, це тому, що деякі відповіді занадто старі, і лише описують поведінку для iOS 9 і раніше, тоді як інші не враховують, що UNUserNotificationCenter доступний лише з iOS 10.
tomacco

12

Xcode 10 Swift 4.2

Щоб відобразити Push Notification, коли ваша програма на першому плані -

Крок 1: додайте делегат UNUserNotificationCenterDelegate у клас AppDelegate.

class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {

Крок 2: Встановіть делегата UNUserNotificationCenter

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

Крок 3: Цей крок дозволить вашій програмі показувати Push Notification, навіть коли ваш додаток на передньому плані

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

    }

Крок 4: Цей крок не є обов'язковим . Перевірте, чи додаток стоїть на передньому плані, а чи на передньому плані, покажіть місцеве 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()
        }
    }

Функція локального сповіщення -

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
Це чудовий приклад необхідності прочитати всі відповіді на нитку. Раніші теми згадують про метод, ніж про делегата, і, нарешті, про цей усі три кроки, які потрібно зробити. ДЯКУЙТЕ, Прашант за повну відповідь!
користувач3069232

Приємно знати, що це вам допомогло. Щасливе кодування
Прашант Гайквад

11

Згідно з документацією на Apple , так, ви можете відображати сповіщення під час роботи програмивведіть тут опис зображення


де я можу записати цю функцію або в делегат програми, або в клас specifc ??
iOS Developer

Що робити, якщо я хочу написати, що methd з огляду зробив завантаження ??
iOS Developer

ви можете писати будь-де, але умова, якщо вона повинна відповідати UNUserNotificationCenterDelegateпротоколу
SPatel

ви не можете записатисьviewDidLoad
SPatel

1
Я пропоную вам продовжити AppDelegateextension AppDelegate: UNUserNotificationCenterDelegate
SPatel

9

Ви можете створити власне сповіщення, яке імітує сповіщення про банер.

Один із способів - створити спеціальний інтерфейс, який буде схожий на банер і може анімувати та реагувати на дотики. Зважаючи на це, ви можете створювати ще кращі банери з ще більшою функціональністю.

Або ви можете шукати api, який робить це для вас, і додавати їх як підфіли до свого проекту.

Ось пара, яку я використав:

https://github.com/terryworona/TWMessageBarManager

https://github.com/toursprung/TSПовідомлення


1
Хоча це посилання може відповісти на питання, краще включити сюди суттєві частини відповіді та надати посилання для довідки. Відповіді лише на посилання можуть стати недійсними, якщо пов’язана сторінка зміниться.
Роберт

1
TWMessageBarManagerможна легко викликати і використовувати через сам appdelegate, оскільки він використовує шаблон дизайну однотонних. Дякуємо за посилання.
Джей Маю

8

Ось код для отримання Push Notification, коли програма перебуває в активному стані (передньому плані чи відкрито). Документація UNUserNotificationCenter

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

Якщо вам потрібно отримати доступ до userInfo з коду використання сповіщення: notification.request.content.userInfo


куди записати цю функцію з огляду навантаження? чи з точки зору контролера?
iOS Developer

Що робити, якщо я можу викликати це у функції, як вкладена функція, це буде називатися> ??
iOS Developer

1
помістіть це в клас AppDelegate. Вам не потрібно викликати цю функцію.
Мілан Джаявардан

4

Додавання цієї лініїHandler для делегування методу вирішило для мене ту саму проблему:

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

Для швидкого 5 для розбору словника 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)")
                            }
                        }
                    }
                }
            }
        }

Щоб отримати вид зверхуКонтролер, на якому ми показуємо 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
    }
}

guardЗатвердження є вашим другом :-)
Ніколя Міар

2

У своєму делегаті програми використовуйте наступний код

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

Як було сказано вище, вам слід скористатися UserNotification.frameworkдля досягнення цього. Але для своїх цілей я мушу показати це в додатку і хотів мати iOS 11стиль, тому я створив невеликий перегляд помічника, можливо, хтось буде корисний.

GitHub iOS 11 Перегляд Push Notification View .


0

Кращий підхід для цього є додавання UNUserNotificationCenterDelegateв AppDelegateза допомогою extension AppDelegate: UNUserNotificationCenterDelegate цього додаткового номера розповідає додаток , щоб мати можливість отримати повідомлення , коли в використанні

І реалізувати цей метод

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

Цей метод буде викликаний делегатом лише в тому випадку, якщо програма знаходиться на передньому плані .

Отже, остаточне впровадження:

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

І щоб зателефонувати цьому, потрібно встановити делегата в AppDelegate, щоб didFinishLaunchingWithOptionsдодати цей рядок

UNUserNotificationCenter.current().delegate = self

Ви можете змінити

completionHandler(.alert) 

з

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

0

Для Swift 5

1) Підтвердьте делегата AppDelegate за допомогою UNUserNotificationCenterDelegate

2) UNUserNotificationCenter.current().delegate = selfвdidFinishLaunch

3) Реалізуйте наведений нижче метод у AppDelegate.

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

Це воно!


-2

Як заявив @Danial Martine, iOS не відображатиме банер / сповіщення про сповіщення. Це за дизайном. Але якщо дійсно доведеться це робити, то є один спосіб. Я теж досяг цього.

1.Завантажте роботу кадру синтаксичного аналізу з Parse FrameWork

2.Імпорт #import <Parse/Parse.h>

3.Додайте наступний код до Вашого методу didReceiveRemoteNotification

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

PFPush подбає про те, як обробляти віддалене сповіщення. Якщо додаток на передньому плані, це відображає попередження, інакше воно відображається вгорі.


оповіщення? ти маєш на увазі огляд попередження?
iphondroid

1
але як отримати зворотній дзвінок для дії кнопки сповіщення
Чарлі

-2

Якщо ваша програма перебуває у передньому плані, це означає, що ви зараз використовуєте той самий додаток. Тому загалом не потрібно показувати сповіщення вгорі.

Але якщо ви хочете показати сповіщення у такому випадку, вам потрібно створити власний перегляд сповіщень або спеціальний перегляд, наприклад Toast, або щось інше, щоб показати користувачеві, що ви отримали сповіщення.

Ви також можете показати значок у верхній частині, якщо у вас є така функція у вашому додатку.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.