Now i have 1 way to do push notification.
I use firebase console( https://console.firebase.google.com/ ) and then assign bundle ID and send push notification.
now i have a question.
How to detection from firebase console on my an application(with swift).
This is my didReceiveRemoteNotification code
didReceiveRemoteNotification Code
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {
if let messageID = userInfo[gcmMessageIDKey] {
print("Message ID1: \(messageID)")
}
var pushId = userInfo["push-id"] as? String
if(pushId == nil){
pushId = "-1"
}
fcmAccessCount(pushId: pushId!)
badgeCount()
switch application.applicationState {
case .active:
break
case .inactive:
break
case .background:
break
default:
break
}
if let aps = userInfo["aps"] as? NSDictionary {
if let alert = aps["alert"] as? String {
let alert = UIAlertController(title: "message is... ", message: alert, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
self.window?.rootViewController?.present(alert, animated: true, completion: nil)
}
}
}
Please write this code in App Delegate class, like below and try-
class AppDelegate: UIResponder, UIApplicationDelegate{
}
#available(iOS 10, *)
extension AppDelegate : UNUserNotificationCenterDelegate {
// Receive displayed notifications for iOS 10 devices.
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
let userInfo = notification.request.content.userInfo
//From here we will navigate to other screens:-
print("User Info : \(userInfo)")
// Change this to your preferred presentation option
//completionHandler([])
completionHandler([.alert,.sound])
}
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: #escaping () -> Void) {
let userInfo = response.notification.request.content.userInfo
// From here we can navigat to required screens:-
// Print full message.
print(userInfo)
completionHandler()
}
}
extension AppDelegate : FIRMessagingDelegate {
/// The callback to handle data message received via FCM for devices running iOS 10 or above.
public func applicationReceivedRemoteMessage(_ remoteMessage: FIRMessagingRemoteMessage) {
}
Related
Push is being received while app is in the background killed by the user, when the user hits the push notification it opens the app and it doesn't crash but it is closed immediately.
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
// If you are receiving a notification message while your app is in the background,
// this callback will not be fired till the user taps on the notification launching the application.
// With swizzling disabled you must let Messaging know about the message, for Analytics
Messaging.messaging().appDidReceiveMessage(userInfo)
// Print message ID.
print("The userInfo is: \(userInfo)")
completionHandler(UIBackgroundFetchResult.newData)
}
The previous method is not even called, or may be it is but I don't know how to debug it, since the application is not running.
Here's the notification object that I send via the server:
apns: {
payload: {
aps: {
alert: {
title: messageObject.authorName,
body: messageObject.content,
},
sound: "notification.wav",
category: "ChatViewController"
}
}
}
That is what is send via the server. The notifications work when the application is in background and not killed, or when the application is in foreground.
I think so when user click on the notification while your application is killed or in background or foreground, below method would be executed. And you have to test it one by one.
First of all check that whether yo are able to see the popup as soon as the application runs when you click on notification. Just copy, paste this code in your AppDelegate Class and comment your didReceiveRemoteNotification method and then check whether your application crash or not.
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
guard let object = response.notification.request.content.userInfo as? [String : AnyObject] else {
return
}
self.normalPopup()
}
/// Alert Popup, if user not exist in our database.
func normalPopup() {
let alert = UIAlertController(title: "Test", message: "Show pop up window.", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in
}))
self.window?.rootViewController?.present(alert, animated: true)
}
If popup window shows, then comment the normalPopup function and replace that function with below code. Then check whether your application crash or not while application killed.
Messaging.messaging().appDidReceiveMessage(userInfo)
Please Lemme know if you are still facing the same issue.
If you use firebase for that first you should define it on application(_ application:, didFinishLaunchingWithOptions:) like underneath:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
if #available(iOS 10.0, *) {
// For iOS 10 display notification (sent via APNS)
UNUserNotificationCenter.current().delegate = self
let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(
options: authOptions,
completionHandler: {_, _ in })
} else {
let settings: UIUserNotificationSettings =
UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
application.registerUserNotificationSettings(settings)
}
application.registerForRemoteNotifications()
Messaging.messaging().delegate = self
FirebaseApp.configure()
return true
}
Also you can Handle notifications when app is ran, with this func:
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
if let messageID = userInfo["gcm.message_id"] {
print("Message ID: \(messageID)")
}
// Print full message.
print(userInfo)
completionHandler(UIBackgroundFetchResult.newData)
}
and
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {
if let messageID = userInfo["gcm.message_id"] {
print("Message ID: \(messageID)")
}
// Print full message.
print(userInfo)
}
and you should set new token to Messaging with this method:
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
Messaging.messaging().apnsToken = deviceToken
let token = deviceToken.map { String(format: "%02.2hhx", $0)}.joined()
print(token)
}
at the end you can handle notifications with below extension
// [START ios_10_message_handling]
#available(iOS 10, *)
extension AppDelegate: UNUserNotificationCenterDelegate {
// Receive displayed notifications for iOS 10 devices.
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
let userInfo = notification.request.content.userInfo
if let messageID = userInfo["gcm.message_id"] {
print("Message ID: \(messageID)")
}
//*************************
// Handle push notification message automatically when app is running
//*************************
print(userInfo)
// Change this to your preferred presentation option
completionHandler([[.alert, .sound]])
}
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: #escaping () -> Void) {
let userInfo = response.notification.request.content.userInfo
// Print message ID.
if let messageID = userInfo["gcm.message_id"] {
print("Message ID: \(messageID)")
}
//*************************
// Handle push notification message after click on it
//*************************
print(userInfo)
completionHandler()
}
}
I'm implemented push notification in my app in this way
//MARK:- Register notifications
func registerForPushNotifications() {
if #available(iOS 10.0, *){
let center = UNUserNotificationCenter.current()
center.delegate = self
center.requestAuthorization(options:[.badge, .alert, .sound]) { (granted, error) in
if (granted)
{
UIApplication.shared.registerForRemoteNotifications()
}
else{
//Do stuff if unsuccessful...
}
// Enable or disable features based on authorization.
}
}
else
{
//If user is not on iOS 10 use the old methods we've been using
let types: UIUserNotificationType = [UIUserNotificationType.badge, UIUserNotificationType.alert, UIUserNotificationType.sound]
let settings: UIUserNotificationSettings = UIUserNotificationSettings( types: types, categories: nil )
UIApplication.shared.registerUserNotificationSettings( settings )
UIApplication.shared.registerForRemoteNotifications()
}
}
//MARK: Push Notifications Delegate Methods
func application( _ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data ) {
var token = ""
for i in 0..<deviceToken.count {
//token += String(format: "%02.2hhx", arguments: [chars[i]])
token = token + String(format: "%02.2hhx", arguments: [deviceToken[i]])
}
USER_DEFAULTS.setValue(token, forKey: "Device_ID")
USER_DEFAULTS.synchronize()
}
func application( _ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error ) {
print( error.localizedDescription )
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {
UIApplication.shared.applicationIconBadgeNumber = 0
alertRemoteNotification(userInfo as NSDictionary)
}
//Code for showing alert when in foreground
func alertRemoteNotification(_ userInfo : NSDictionary)
{
if UIApplication.shared.applicationState == .active {
if let aps = userInfo as? NSDictionary {
if let apsDidt = aps.value(forKey: "aps") as? NSDictionary {
if let alertDict = apsDidt.value(forKey: "alert") as? NSDictionary {
if let notification_type = alertDict.value(forKey: "name") as? String {
if let notification_Message = alertDict.value(forKey: "body") as? String {
let alert = UIAlertController(title: notification_type.capitalized + " Alert", message: notification_Message, preferredStyle: UIAlertControllerStyle.alert)
let okayBtn = UIAlertAction(title: "OK", style: .default, handler: { (action) -> Void in
// When Okay
UIApplication.shared.applicationIconBadgeNumber = 0
if #available(iOS 10.0, *) {
let center = UNUserNotificationCenter.current()
center.removeAllDeliveredNotifications() // To remove all delivered notifications
center.removeAllPendingNotificationRequests()
} else {
// Fallback on earlier versions
UIApplication.shared.cancelAllLocalNotifications()
}
let rootViewController = self.window!.rootViewController as! UINavigationController
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let dashBoardVC = mainStoryboard.instantiateViewController(withIdentifier: "DashBoardVC") as! DashBoardVC
rootViewController.pushViewController(dashBoardVC, animated: false)
})
let cancelBtn = UIAlertAction(title: "Cancel", style: .default, handler: { (action) -> Void in
UIApplication.shared.applicationIconBadgeNumber = 0
if #available(iOS 10.0, *) {
let center = UNUserNotificationCenter.current()
center.removeAllDeliveredNotifications() // To remove all delivered notifications
center.removeAllPendingNotificationRequests()
} else {
// Fallback on earlier versions
UIApplication.shared.cancelAllLocalNotifications()
}
})
alert.addAction(okayBtn)
alert.addAction(cancelBtn)
self.window?.rootViewController!.present(alert, animated: true, completion: nil)
}
}
}
}
}
}
else {
let rootViewController = self.window!.rootViewController as! UINavigationController
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let dashBoardVC = mainStoryboard.instantiateViewController(withIdentifier: "DashBoardVC") as! DashBoardVC
rootViewController.pushViewController(dashBoardVC, animated: false)
}
}
//Delegate methods
#available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler([.sound, .alert, .badge])
UIApplication.shared.applicationIconBadgeNumber = 0
}
#available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
let userInfo = response.notification.request.content.userInfo as NSDictionary
completionHandler()
self.alertRemoteNotification(userInfo as NSDictionary)
}
I could able to access the responce after tapping notification banner but the actual issue is when i'm in foreground i need to show an alert with the notification responce without tapping on notification banner. Please let me know how can get responce without tapping on notification banner.
iOS 10+ Provides delegate userNotificationCenter:willPresentNotification:withCompletionHandler
Asks the delegate how to handle a notification that arrived while the
app was running in the foreground.
And this will call only if app opened.
Also you can use CONTENT-AVAILABLE=1 for triggering methods.
FLOW:(Without Taping Notification, content-available:1)
App Opened State:- willPresentNotification(ios10+) -> didReceiveRemoteNotification:fetchCompletionHandler
App in Background:- didReceiveRemoteNotification:fetchCompletionHandler
App Closed:- You won't get notification data unless, the app opened by clicking Notification
Alternate method: Using Rich Notification
You can use Notification Extensions to create custom push notifications(contents including images/videos). Notification Service Extension & Notification Content Extension used to achieve this. mutable-content:1 required to trigger this. Here you can download images, get data, etc. [But the data can be shared with App ONLY through UserDefaults(App Groups), correct me if i'm wrong]
You could search for some random tutorials
Create notification service extension to process notification data. you will get 30seconds to process pushnotification via notification service extension
override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: #escaping (UNNotificationContent) -> Void) {
if let copy = request.content.mutableCopy() as? UNMutableNotificationContent {
// Process your notification here
contentHandler(copy)
}
}
Hope this will help you
#available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler([.sound, .alert, .badge])
UIApplication.shared.applicationIconBadgeNumber = 0
// Added This line
alertRemoteNotification(notification.request.content.userInfo as NSDictionary)
}
Working without any issues.
I need help finishing this piece of code so the app will show badge number when a push notification is received, I can receive push notification, but just no badge on app, here is the code
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any],
fetchCompletionHandler completionHandler: #escaping
(UIBackgroundFetchResult) -> Void) {
if let aps = userInfo["aps"] as? NSDictionary, let _ = aps["alert"] as? String, let sound = aps["sound"] as? String
{
if let systemSound = SystemSoundID(sound) {
AudioServicesPlayAlertSound(systemSound)
}
NotificationCenter.default.post(name: Notification.Name(rawValue: SystemSetting.refreshCouponListNotification), object: nil)
completionHandler(UIBackgroundFetchResult.newData)
}
}
There is the two Methods are Called for Push notification
Foreground Method
Background Method
1.Foreground Method.
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void)
Get content of Request of Notification
let content = notification.request.content
2.Background Method
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: #escaping () -> Void)
Get content of Request of Notification
let content = response.notification.request.content
Get Badge Count
let badge = content.badge as! Int
Follow these steps to set badge count in iOS :
1.Implement logic to calculate count in backend and send that count through Push notification like :
{
"aps" : {
"alert" : "You got your Push Message.",
"badge" : 9
}
}
2.Get Badge count from Push notification response :
let pushContent = response.notification.request.content
let badgeCount = content.badge as! Int
3.set badge count in didReceiveRemoteNotification method :
UIApplication.sharedApplication().applicationIconBadgeNumber = badgeCount
Currently I have my app set up to receive push notifications in ios 9 where it works perfectly but with iOS 10 I'm not receiving them. I've looked over various responses on stackoverflow and came across this:
Push Notifications not being received on iOS 10, but working on iOS 9 and before
which appears to work for the poster. I'm not entirely sure what code I'm supposed to add under the willPresentNotification and didReceiveNotificationResponse sections. If anyone has any examples of how these sections work it will be appreciated. This is my relevant code for handling push notifications so far:
import UserNotifications
import Whisper
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
registerForPushNotifications(application)
}
//MARK: Push Notification Settings
func registerForPushNotifications(application: UIApplication) {
//check to see if phone is updated to iOS 10
if #available(iOS 10.0, *){
UNUserNotificationCenter.currentNotificationCenter().delegate = self
UNUserNotificationCenter.currentNotificationCenter().requestAuthorizationWithOptions([.Badge, .Sound, .Alert], completionHandler: {(granted, error) in
if (granted)
{
UIApplication.sharedApplication().registerForRemoteNotifications()
}
else{
print("registering for push notifications unsuccessful")
}
})
}
else{ //If user is not on iOS 10 use the old methods we've been using
let notificationSettings = UIUserNotificationSettings(
forTypes: [.Badge, .Sound, .Alert], categories: nil)
application.registerUserNotificationSettings(notificationSettings)
}
}
//Notification handling for iOS 10
#available(iOS 10.0, *)
func userNotificationCenter(center: UNUserNotificationCenter, willPresentNotification notification: UNNotification, withCompletionHandler completionHandler: (UNNotificationPresentationOptions) -> Void) {
//Handle the notification - NOT SURE WHAT GOES HERE
}
#available(iOS 10.0, *)
func userNotificationCenter(center: UNUserNotificationCenter, didReceiveNotificationResponse response: UNNotificationResponse, withCompletionHandler completionHandler: () -> Void) {
//Handle the notification -NOT SURE WHAT GOES HERE
}
//This is called if user selects to receive push notifications
func application(application: UIApplication, didRegisterUserNotificationSettings notificationSettings: UIUserNotificationSettings) {
// if notificationSettings.types != .None {
application.registerForRemoteNotifications()
// }
}
func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
let tokenChars = UnsafePointer<CChar>(deviceToken.bytes)
var tokenString = ""
for i in 0..<deviceToken.length {
tokenString += String(format: "%02.2hhx", arguments: [tokenChars[i]])
}
//save device token to keychain
self.deviceToken = tokenString
userInfo.sharedInstance.savePushNotDeviceToken(tokenString)
NSUserDefaultsManager.sharedManager.pushNotifications = true
//register device token to api
registerPushNotificationDevice(tokenString)
print("Device Token:", tokenString)
}
func application(application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: NSError) {
print("Failed to register:", error)
//save push notifications state
NSUserDefaultsManager.sharedManager.pushNotifications = false
}
//In- App push notifications
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
if application.applicationState == .Active {
let navigationController = self.window!.rootViewController as! UINavigationController
let alert = [String: String]()
let title = ""
let body = ""
// Default printout of userInfo
print("All of userInfo:\n\( userInfo)\n")
if let aps = userInfo["aps"] as? NSDictionary {
if let alert = aps["alert"] as? NSDictionary {
if let title = alert["title"] as? NSString {
if let body = alert["body"] as? NSString {
let announcement = Announcement(title: title as String, subtitle: body as String, image: UIImage(named: "Image"))
show(shout: announcement, to: navigationController)
}
}
}
}
}
}
}
For remote and local notification in iOS 10 we have UserNotifications.framework. To handle notification there are two delegate methods of UNUserNotificationCenterDelegate available in UserNotifications.framework. You need to do the same code you are doing in didReceiveRemoteNotification method to get userInfo.This two methods are available to handle userInfo according to your app requirements.
//UNUserNotificationCenterDelegate delegate methods to get userInfo
#available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (_ options: UNNotificationPresentationOptions) -> Void) {
//Called when a notification is delivered to a foreground app.
let userInfo = notification.request.content.userInfo as? NSDictionary
print("\(userInfo)")
}
#available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
// Called to let your app know which action was selected by the user for a given notification.
let userInfo = response.notification.request.content.userInfo as? NSDictionary
print("\(userInfo)")
}
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!!!")
}
}
}
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
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.
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.
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)
}
None of these answers are good with recent IOS versions
shouldAlwaysAlertWhileAppIsForeground will crash on >= IOS 12
assigning UNUserNotificationCenter.current().delegate changes the behavior of background push notifications. UIApplicationDelegate.didReceiveRemoteNotification() is no longer called, when push notification is received and app is on background (until user clicks the notification).