UNUserNotificationCenterDelegate is not working when is remove from background. It is working fine while app stays in foreground and background.
Here is code
extension AppDelegate: UNUserNotificationCenterDelegate {
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler([.alert, .sound])
}
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
let rootViewController = self.window!.rootViewController as! UINavigationController
let mainStoryboard = UIStoryboard(name: "Main", bundle: nil)
let profileViewController = mainStoryboard.instantiateViewController(withIdentifier: "SampleViewController") as! SampleViewController
rootViewController.pushViewController(profileViewController, animated: true)
completionHandler()
}
}
When app is remove from background delegate method is not called. Please help me out
When adding UserNotifications framework to a project, here are 5 things to check:
1) If you are dealing with remote notifications, be sure you have enabled that in your project's capabilities settings page of Xcode.
See figure 1
If that gives you an error, you probably need to log into your apple developer account and create a key with push notification credentials. The end result gives you a .p8 file to download. The creation of this file will clear up the error. The file itself is needed on the server that sends push notifications to your app/device. If you need help with this, check out this tutorial.
2) Add import line to the top of your AppDelegate file
import UserNotifications
3) Add UNUserNotificationCenterDelegate to your AppDelegate class declaration line.
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {...
4) Set UNUserNotificationCenter delegate to self in the application:didFinishLaunchingWithOptions method.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
//...
UNUserNotificationCenter.current().delegate = self
//...
return true
}
5) Add your delegate functions (if you want to use them)
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
NSLog("Application delegate method userNotificationCenter:didReceive:withCompletionHandler: is called with user info: %#", response.notification.request.content.userInfo)
//...
}
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
NSLog("userNotificationCenter:willPresent")
//...
completionHandler([.alert])
}
Hope that helps.
check didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? method. When user taps a notification banner (and the app is terminated) the app is started, this method is called and launchOptions contains notification info. Therefore you can understand (by checking the launchOptions) that the app is launched by tapping on notification banner and navigate user wherever you want to
Related
There are many articles regarding how to take user to a specific view when he/she taps on a push notification using App Delegate. But is it possible to do this using only the SwiftUI App Lifecycle?
There isn't away using only SwiftUI. You will have to use the AppDelegate to respond to notifications.
class AppDelegate: NSObject, UIApplicationDelegate {
func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
UNUserNotificationCenter.current().delegate = self
return true
}
}
extension AppDelegate: UNUserNotificationCenterDelegate {
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
print("Notification received with identifier \(notification.request.identifier)")
completionHandler([.banner, .sound])
}
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
// do what you want here
}
}
I have implemented the push notification in the app. I am getting callbacks on the following delegate method whenever the push comes.
func application(_: UIApplication,
didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void)
I have implemented the following delegate method To show the push notification when the app is in the foreground.
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void)
{
completionHandler([.alert, .badge, .sound])
}
Unfortunately, it is not working every time. Irrespective of the app state I'm getting the callback on didReceiveRemoteNotification method. Is there any particular reason for this behavior? Am I missing something?
Thanks in advance
I think you have to use the userNotificationCenter with the "didReceive response" signature instead of the application(didReceiveRemoteNotification userInfo:..)
// MARK: Notification handling
// If the app is in the background
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
let id = response.notification.request.identifier
print("Received notification with ID = \(id)")
completionHandler()
}
// If the app is in the foreground
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
let id = notification.request.identifier
print("Received notification with ID = \(id)")
completionHandler([.sound, .alert])
}
Also have your AppDelegate be UNUserNotificationCenter delegate.
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
UNUserNotificationCenter.current().delegate = self
}
.
.
.
}
I want to find out which method is triggered when a terminated application receives a notification from my server. The application is being developed through Swift 4, my Deployment Target is 10.3 and Firebase is used to send notifications to users.
I've configured my application in AppDelegate.swift:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
FirebaseApp.configure()
Messaging.messaging().delegate = self
UNUserNotificationCenter.current().delegate = self
}
Additionally, I created the extension:
#available(iOS 10, *)
extension AppDelegate : UNUserNotificationCenterDelegate {
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
}
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: #escaping () -> Void) {
}
}
When the app receives a notification and it's running or it's in background, the method "willPresent" is called and when the user taps on the notification and decide to open it, the method "didReceive" is called. No method is triggered if the application is terminated.
Am I doing something wrong?
So when my app is not currently open and it receives a push notification, the "didrecieveremotenotification" works perfectly fine when the banner appears and you press it. But when the app is open, no banner at all appears. I want the push notification to work when the app is open aswell.
I tried using UNNotificationCenter but lost push notifications in general.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
UNUserNotificationCenter.current().delegate = self
UNUserNotificationCenter.current().requestAuthorization(options: [.badge, .sound, .alert], completionHandler: {(granted, error) in
if (granted) {
UIApplication.shared.registerForRemoteNotifications()
} else{
print("Notification permissions not granted")
}
})
}
//Called when a notification is delivered to a foreground app.
public func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Swift.Void) {
completionHandler([.sound, .alert, .badge])
}
//Called to let your app know which action was selected by the user for a given notification.
public func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Swift.Void) {
completionHandler()
}
Update: UNUserNotificationCenter.current().requestAuthorization runs
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error)
when permission is granted.
however when I don't use UNNotificationCenter and use old method it doesn't fail.
Why would one method fail to register for remote notifications but the other not?
Update 2: Was working in simulator lol, that's why it was failing. However now when I run the
UNUserNotificationCenterDelegate
methods only the
public func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive method works and not the
public func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent
Update 3: I've ran out of possible things to try. What would be stopping the code from firing willPresent but not didReceive. This is brutal. Has anyone ever had this issue before?
Update 4: SOLVED. The service I'm using for the push notifications requires the user to be disconnected from the service to send the push notification. It automatically disconnects you when you're in the background, which is why that was working and it wasn't working in the foreground.
Weird way for them to configure that, I'll probably send an email.
Implement UNUserNotificationCenterDelegate delegate methods to get notification (tray at top) while app is in foreground. But it will only work with IOS 10.
In your didFinishLaunchingWithOptions method set UNUserNotificationCenterDelegate delegate like this.
UNUserNotificationCenter.current().delegate = self
Implement Delegate methods...
//Called when a notification is delivered to a foreground app.
public func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Swift.Void) {
completionHandler([.sound, .alert, .badge])
}
//Called to let your app know which action was selected by the user for a given notification.
public func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Swift.Void) {
completionHandler()
}
I recently set up notifications on my application, I can send via php and no worries, everything works fine.
Since last week, I am trying to find out if a push notification is received by the phone or not..
I can know when someone clicks on it but if the person does not click on it and prefer to open the application, it does not work..
Is there not a simple function that can tell me if a notification has just been received by the application ?
In my AppDelegate.swift :
import UIKit
import UserNotifications
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {
...
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Check if launched from notification
if let notification = launchOptions?[UIApplicationLaunchOptionsKey.remoteNotification] as? [String: AnyObject] {
//print(notification)
window?.rootViewController?.present(ViewController(), animated: true, completion: nil)
}
else{
//print("ici ?")
registerForRemoteNotification()
}
return true
}
...
//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])
}
//Called to let your app know which action was selected by the user for a given notification.
#available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
completionHandler()
}
...
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
**print("here ?")**
switch((application.applicationState)){
case UIApplicationState.inactive:
print("Inactive")
//Show the view with the content of the push
completionHandler(.newData)
case UIApplicationState.background:
print("Background")
//Refresh the local model
completionHandler(.newData)
default:
print("Active")
//Show an in-app banner
completionHandler(.newData)
break
}
}
}
Problem : I never pass in didReceiveRemoteNotification :/
The "print here" is never displayed.
I have a mistake on this line :
Instance method
'application(application:didReceiveRemoteNotification:fetchCompletionHandler:)'
nearly matches optional requirement
'application(_:didReceiveRemoteNotification:fetchCompletionHandler:)'
of protocol 'UIApplicationDelegate'
But I do not understand :/
Do you have an idea ?
Thx for your help ^^
It's rather common mistake since the conversion to Swift 3 - you're using Swift 2 method.
The right signature of this method in Swift 3 is:
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
print("here?")
}