在前台iOS中获取App时的推送通知


189

我在我的应用程序中使用了推送通知服务。当应用程序在后台运行时,我可以在通知屏幕上看到通知(当我们从iOS设备顶部向下滑动时显示的屏幕)。但是如果应用程序位于前台,则委托方法

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

正在被呼叫,但通知未显示在通知屏幕中。

我想在通知屏幕上显示通知,而不管应用程序是在后台还是在前台。寻找解决方案让我很累。任何帮助是极大的赞赏。


35
苹果如果您的应用程序在前台运行时收到本地或远程通知,则您有责任以特定于应用程序的方式将信息传递给用户。
Lauri Lehmijoki '16

2
一些最新的(
azmeuk

1
iOS 9.3及以下版本的推送通知不支持前台吗?
阿努拉格·夏尔马

@Lauri Lehmijoki链接?我没有在官方网站上找到它
Vyachaslav Gerchicov '18

1
我在离子方面也面临着同样的问题……
Mohd Ali说,

Answers:


203

要在应用程序处于前台状态时显示横幅消息,请使用以下方法。

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

什么时候调用此方法?
Uma Madhavi

请指导我,当我的应用程序背景或前景出现时,我会从顶部开始显示通知。自2周以来,我一直在使用推送通知。我能够从服务器接收消息。
Uma Madhavi

@UmaMadhavi您可以收到推送通知吗?
chengsam '16

21
不要忘记将Notification Center委托设置为应用程序委托: UNUserNotificationsCenter.current().delegate = self在应用程序didFinishLaunchingWithOptions
Achintya Ashok中

2
对于仍在挣扎的用户,其UNUserNotificationsCenter而非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];          
    }    
}

这可行。有关其功能的更多信息;当应用程序位于前台时,将出现一个本机UI警报框,其中包含通知文本(title稍大的粗体文本,下面的message较小文本。底部的“确定”按钮)。选项applicationIconBadgeNumber设置为0是为了隐藏在Springboard中应用程序图标顶部显示的数字(例如,表示邮件应用程序中未读消息的数量)。在此示例中,我不知道是否需要该选项。
jwinn

这对UNnotification和UILocalNotification都起作用吗?
user6631314 '18年

38

对于可能感兴趣的任何人,我最终创建了一个自定义视图,该视图看起来像顶部的系统推送横幅,但添加了一个关闭按钮(小蓝色X)和一个点击消息以执行自定义操作的选项。它还支持在用户有时间读取/关闭旧通知之前到达多个通知的情况(不限制可以堆积多少个…)

链接到GitHub:AGPushNote

用法基本上是在线的:

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

在iOS7上看起来像这样(iOS6具有iOS6外观...)

在此处输入图片说明


1
现在也在Swift中重新构想github.com/charliewilliams/CWNotificationBanner(由我负责)
成功

很好,这很有用。
无夜之星辰

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协议。
Nik Kov

如果我想显示警报而不是此通知呢?
Mihir Oza

@MihirOza您想要UIAlertController吗?
Ashwini Chougale,2015年

我知道,但我不希望应用程序处于活动状态时弹出通知。我只想在我的应用中发出警报。
Mihir Oza

24

如果应用程序在前台运行,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];
    }

迅速:

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通知中心中留下一个条目
2014年

3
但是,当推送通知到来时,我不会启动本地通知。我会启动类似的行为,例如@ Rick77:显示警报或一些烤面包机。我猜我不必再经历操作系统要我处理的事情。
法比奥·奥利维拉

3
此解决方案有效,因为以相同的方式处理本地和远程,当应用程序处于前台时,在出现远程通知时创建位置通知不会显示任何内容。解决方案是使用警报或自定义警报
Hammer 2014年

18
这实际上是行不通的。来自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 2013年

3
我不确定@ Ab'initio,但是在iOS中并非所有应用程序都相同。我想库存的Mail应用程序正在使用某种私有API,而这些私有API在公共SDK中不可用。或者,通知代码使Apple的Mail应用程序ID成为异常。
丹尼尔·马丁2013年

1
什么??我快要遭受狂暴的袭击。
乔什(Josh)

@DanielMartínü可以告诉我,我怎么会收到通知在前台状态的iOS 8.0
迪利普·蒂瓦里

9
请记住,此答案仅适用于iOS 9及更低版本。从iOS 10开始,Apple引入了新的API来处理通知(UNUserNotificationCenter API)。连同新的API,现在可以在应用程序位于前台时显示通知。因此,如果您因此问题中的答案不同而感到困惑,那是因为其中一些答案太旧了,仅描述了iOS 9及更高版本的行为,而其他答案并未考虑到UNUserNotificationCenter 只能从iOS 9 获得iOS 10
tomacco

12

Xcode 10 Swift 4.2

要在您的应用程序位于前台时显示推送通知-

步骤1:在AppDelegate类中添加委托UNUserNotificationCenterDelegate。

class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {

步骤2:设置UNUserNotificationCenter委托

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

步骤3:即使您的应用程序位于前台,此步骤也将允许您的应用程序显示“推送通知”

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

    }

步骤4:此步骤是可选的。检查您的应用程序是否在前台,以及是否在前台,然后显示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()
        }
    }

本地通知功能-

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
这是需要阅读对线程的所有答复的一个很好的例子。较早的线程提到的是方法,而不是委托,最后是您需要完成的所有这三个步骤。谢谢Prashant提供完整的答案!
user3069232

很高兴知道它对您有所帮助。快乐的编码
Prashant Gaikwad

10

根据apple 文档,是的,您可以在应用运行时显示通知在此处输入图片说明


我在哪里可以在应用程序委托或特定类中编写该函数?
iOS开发人员

如果我想在加载时写那个方法怎么办?
iOS开发人员

您可以在任何情况下写任何内容,但条件应符合UNUserNotificationCenterDelegate协议
SPatel

您不能写viewDidLoad
SPatel

1
我建议您扩展AppDelegateextension AppDelegate: UNUserNotificationCenterDelegate
SPatel

9

您可以创建自己的模仿横幅警报的通知。

一种方法是创建一个自定义uiview,该uiview看起来像横幅,可以设置动画并响应触摸。考虑到这一点,您可以创建具有更多功能的更好的横幅。

或者,您可以寻找一个为您执行此操作的api,然后将它们作为podfile添加到您的项目中。

这是我使用过的几个:

https://github.com/terryworona/TWMessageBarManager

https://github.com/toursprung/TSMessages


1
尽管此链接可以回答问题,但最好在此处包括答案的基本部分,并提供链接以供参考。如果链接页面发生更改,仅链接的答案可能会无效。
罗伯特

1
TWMessageBarManager可以通过appdelegate本身轻松地调用和使用,因为它使用单例设计模式。感谢您的链接。
杰·马尤

8

这是在应用程序处于活动状态(前台或打开)时接收推送通知的代码。 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开发人员

如果我可以在函数中将其作为嵌套函数调用,该怎么办呢?
iOS开发人员

1
将其放在AppDelegate类中。您不必调用此函数。
米兰贾亚瓦达内'18

4

在我的委托方法中添加了completionHandler行,为我解决了同样的问题:

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

对于Swift 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的top viewController

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声明是您的朋友:-)
Nicolas Miari

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

这个最好的办法是增加UNUserNotificationCenterDelegateAppDelegate使用extension AppDelegate: UNUserNotificationCenterDelegate 该扩展告诉应用程序能在使用时获得通知

并实现此方法

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

仅当应用程序位于Foreground中时,才会在委托上调用此方法。

所以最终实现:

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 = selfdidFinishLaunch

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.下载从解析帧工作解析FrameWork的

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

3.将以下代码添加到didReceiveRemoteNotification方法中

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

PFPush将注意如何处理远程通知。如果App在前台,则显示警报,否则在顶部显示通知。


警报?您的意思是警惕的观点?
iphondroid 2014年

1
但是如何通过警报按钮操作回电
Charlie

-2

如果您的应用程序处于前台状态,则表示您当前正在使用同一应用程序。因此,通常无需在顶部显示通知。

但是,即使在这种情况下,如果您想显示通知,也必须创建自定义的“警报视图”或“自定义视图”(例如Toast)或其他向用户显示已收到通知的东西。

如果您的应用中具有这种功能,也可以在顶部显示徽章。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.