Getting local notifications to show while app is in foreground Swift 3
Solution 1
There is a delegate method to display the notification when the app is open in iOS 10. You have to implement this in order to get the rich notifications working when the app is open.
extension ViewController: UNUserNotificationCenterDelegate {
//for displaying notification when app is in foreground
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
//If you don't want to show notification when app is open, do something here else and make a return here.
//Even you you don't implement this delegate method, you will not see the notification on the specified controller. So, you have to implement this delegate and make sure the below line execute. i.e. completionHandler.
completionHandler([.alert, .badge, .sound])
}
// For handling tap and user actions
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
switch response.actionIdentifier {
case "action1":
print("Action First Tapped")
case "action2":
print("Action Second Tapped")
default:
break
}
completionHandler()
}
}
In order to schedule a notification in iOS 10 and providing a badge
override func viewDidLoad() {
super.viewDidLoad()
// set UNUserNotificationCenter delegate to self
UNUserNotificationCenter.current().delegate = self
scheduleNotifications()
}
func scheduleNotifications() {
let content = UNMutableNotificationContent()
let requestIdentifier = "rajanNotification"
content.badge = 1
content.title = "This is a rich notification"
content.subtitle = "Hello there, I am Rajan Maheshwari"
content.body = "Hello body"
content.categoryIdentifier = "actionCategory"
content.sound = UNNotificationSound.default
// If you want to attach any image to show in local notification
let url = Bundle.main.url(forResource: "notificationImage", withExtension: ".jpg")
do {
let attachment = try? UNNotificationAttachment(identifier: requestIdentifier, url: url!, options: nil)
content.attachments = [attachment!]
}
let trigger = UNTimeIntervalNotificationTrigger.init(timeInterval: 3.0, repeats: false)
let request = UNNotificationRequest(identifier: requestIdentifier, content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request) { (error:Error?) in
if error != nil {
print(error?.localizedDescription ?? "some unknown error")
}
print("Notification Register Success")
}
}
In order to register in AppDelegate we have to write this piece of code in didFinishLaunchingWithOptions
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
registerForRichNotifications()
return true
}
I have defined actions also here. You may skip them
func registerForRichNotifications() {
UNUserNotificationCenter.current().requestAuthorization(options: [.alert,.badge,.sound]) { (granted:Bool, error:Error?) in
if error != nil {
print(error?.localizedDescription)
}
if granted {
print("Permission granted")
} else {
print("Permission not granted")
}
}
//actions defination
let action1 = UNNotificationAction(identifier: "action1", title: "Action First", options: [.foreground])
let action2 = UNNotificationAction(identifier: "action2", title: "Action Second", options: [.foreground])
let category = UNNotificationCategory(identifier: "actionCategory", actions: [action1,action2], intentIdentifiers: [], options: [])
UNUserNotificationCenter.current().setNotificationCategories([category])
}
If you want that your notification banner should be shown everywhere in the entire application, then you can write the delegate of UNUserNotificationDelegate
in AppDelegate
and make the UNUserNotificationCenter
current delegate to AppDelegate
extension AppDelegate: UNUserNotificationCenterDelegate {
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
print(response.notification.request.content.userInfo)
completionHandler()
}
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler([.alert, .badge, .sound])
}
}
Check this link for more details
https://www.youtube.com/watch?v=Svul_gCtzck
Github Sample
https://github.com/kenechilearnscode/UserNotificationsTutorial
Here is the output
Solution 2
Swift 3 | iOS 10+
Assuming you know how to schedule a local notification:
func scheduleLocalNotification(forDate notificationDate: Date) {
let calendar = Calendar.init(identifier: .gregorian)
let requestId: String = "123"
let title: String = "Notification Title"
let body: String = "Notification Body"
// construct notification content
let content = UNMutableNotificationContent()
content.title = NSString.localizedUserNotificationString(forKey: title, arguments: nil)
content.body = NSString.localizedUserNotificationString(forKey: body, arguments: nil)
content.sound = UNNotificationSound.default()
content.badge = 1
content.userInfo = [
"key1": "value1"
]
// configure trigger
let calendarComponents: [Calendar.Component] = [.year, .month, .day, .hour, .minute]
let dateComponents = calendar.dateComponents(calendarComponents, from: notificationDate)
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: false)
// create the request
let request = UNNotificationRequest.init(identifier: requestId, content: content, trigger: trigger)
// schedule notification
UNUserNotificationCenter.current().add(request) { (error: Error?) in
if let error = error {
// handle error
}
}
}
You need to make your AppDelegate
implement the UNUserNotificationCenterDelegate
protocol, and set it as the notification center's delegate with UNUserNotificationCenter.current().delegate = self
.
// AppDelegate.swift
import UIKit
import UserNotifications
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions
launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// set app delegate as notification center delegate
UNUserNotificationCenter.current().delegate = self
}
}
extension AppDelegate: UNUserNotificationCenterDelegate {
// called when user interacts with notification (app not running in foreground)
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse, withCompletionHandler
completionHandler: @escaping () -> Void) {
// do something with the notification
print(response.notification.request.content.userInfo)
// the docs say you should execute this asap
return completionHandler()
}
// called if app is running in foreground
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent
notification: UNNotification, withCompletionHandler completionHandler:
@escaping (UNNotificationPresentationOptions) -> Void) {
// show alert while app is running in foreground
return completionHandler(UNNotificationPresentationOptions.alert)
}
}
Now your local notifications will appear when your app is in the foreground.
See the UNUserNotificationCenterDelegate docs for reference.
Solution 3
Key to getting your notifications to show up while your app is in the foreground is also setting:
content.setValue(true, forKey: "shouldAlwaysAlertWhileAppIsForeground")
in your UNNotificationRequest
. As for the rest, see the excellent answer by Rajan Maheshwari.
Solution 4
When your app is open in the foreground userNotificationCenter method call
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void)
{
completionHandler(.alert)
}
Related videos on Youtube
user6820041
Updated on July 09, 2022Comments
-
user6820041 almost 2 years
Apparently this is now possible with ios10 :
optional func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: (UNNotificationPresentationOptions) -> Void)
This answer basically says the tools needed to do it:
Displaying a stock iOS notification banner when your app is open and in the foreground?
I'm just not really understanding how to put it all together.
I dont know how important this is, but I'm not able to keep the optional func and xcode wants me to switch it to private.
I'm trying to show the badge, and the docs provide
static var badge: UNNotificationPresentationOptions { get }
Little lost here.
And then I'm assuming if I want to exclude a certain view controller from getting these badges and I'm not using a navigation controller this code I found would work? : var window:UIWindow?
if let viewControllers = window?.rootViewController?.childViewControllers { for viewController in viewControllers { if viewController.isKindOfClass(MyViewControllerClass) { print("Found it!!!") } } }
-
ArgaPK about 6 yearsWhich method get executed when the app is in background and we receive the notification??
-
-
user6820041 over 7 yearsAwesome, awesome answer. Thank you.
-
Himanshu Moradiya about 7 yearsnow suppose i want to set image from NSURL means web then how can i set this ?
-
James about 7 yearsYou should NOT have to set this if your delegate for
UNUserNotificationCenterDelegate
and the registration of the action category are set up correctly. The first method in the delegate is there to process this app-in-foreground case. Setting this value is undocumented and may run foul of app store guidelines. -
YMonnier about 7 yearsVery nice answer!!
-
Bob over 6 yearsawesome bro awesome! Charlie Sheen would say you were a rock star! If you have foreground notifications just copy and paste this snippet of code and you are done!.
-
Rajesh over 6 yearsIn iOS 10 works well but In iOS 9 How to show the notification over the app?
-
Rajan Maheshwari over 6 years@Rajesh you have to use some custom banner or BannerView or any third party which drops a view from top whenever a notification arrives.
-
Rajesh over 6 years@RajanMaheshwari Thanks for reply, is there any third party available?i am new to iOS.
-
ArgaPK about 6 yearsWhich method get executed when the app is in background and we receive the notification??
-
ArgaPK about 6 yearsWhich method get executed when the app is in background and app receive the notification??
-
Derek Soike about 6 years@ArgaPK If your app is in the background and a notification appears on a user's device, no method is called. Only when a user interacts with a notification does the
userNotificationCenter(didReceive response)
method get called. -
Chris Conway almost 6 years@James, thanks, I've been investigating this in ObjC+iOS12 scenario and most answers don't actually clarify on the correctness of the code, assuming the line is necessary and fixing the line to work, rather than determining if it's needed or actually the recommended approach.
-
A R over 4 yearsis it still working with iOS 13? i did not see its working.
-
Kudos about 3 yearsHow you this code is working?
let url = Bundle.main.url(forResource: "notificationImage", withExtension: ".jpg")
I am getting nil in url when passing image name and its extension from asset. -
Massmaker almost 3 yearsThis stuff is no longer valid - the app crashes with an error - SetValueForUndefinedKey: "shouldAlwaysAlertWhileAppIsForeground"
-
Erkki Nokso-Koivisto almost 3 yearsyep, assigning NUserNotificationCenter.current().delegate will break background push notifications (UIApplicationDelegate.didReceiveRemoteNotification() is no longer called)
-
Kishan Bhatiya over 2 years@RajanMaheshwari, are we able to handle click on local push notification (without any action identifier) when an app is in an in-active state (killed state)?
-
Rajan Maheshwari over 2 years@KishanBhatiya
didReceive
is your delegate which is called whenever you tap on a local notification even without any action identifiers in whichever state your app in