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

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

正在被调用,但通知屏幕上没有显示通知。

我想在通知屏幕上显示通知,不管应用程序是在后台还是前台。我厌倦了寻找解决办法。任何帮助都非常感激。


当前回答

Xcode 10 Swift 4.2

当你的应用程序在前台时,显示推送通知

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

class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {

步骤2:设置UNUserNotificationCenter委托

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

第三步:这一步将允许你的应用程序显示推送通知,即使你的应用程序在前台

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

    }

步骤4:该步骤是可选的。检查你的应用程序是否在前台,如果在前台,然后显示本地推送通知。

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

其他回答

下面的代码将为您工作:

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

也适用于iOS 14+,不需要手动处理任何警报或视图,只需让iOS做它的事情

在里面,我们重新收到通知替换如下代码

func userNotificationCenter(
    _ center: UNUserNotificationCenter,
    willPresent notification: UNNotification,
    withCompletionHandler completionHandler:
    @escaping (UNNotificationPresentationOptions) -> Void
  ) {
    
    if (UIApplication.shared.applicationState == .inactive || UIApplication.shared.applicationState == .background) {
      if #available(iOS 14.0, *) {
        completionHandler([[.banner, .sound]])
      } else {
        completionHandler([.alert, .sound])
      }
    } else {
      if #available(iOS 14.0, *) {
        completionHandler([[.banner]])
      } else {
        completionHandler([.alert])
      }
    }
  }

要注意的主要事情是不要使用声音,而在前景,它不会显示横幅

最好的方法是通过使用扩展AppDelegate: UNUserNotificationCenterDelegate在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]))

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

iOS 14 +

下面这个答案有一个不同之处,.alert已弃用,使用.banner:

class AppDelegate: NSObject, UIApplicationDelegate, UNUserNotificationCenterDelegate {
    func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil
    ) -> Bool {
        UNUserNotificationCenter.current().delegate = self

        return true
    }

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