Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting local notifications to show while app is in foreground Swift 3

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!!!")         }     } } 
like image 352
user6820041 Avatar asked Sep 26 '16 22:09

user6820041


People also ask

How do I show local notification when an app is in foreground iOS?

In order to display the notification when the app is foreground/open, you need to add a delegate method. You have to implement UNUserNotificationCenterDelegate in order to get the local notification when the app is open. in application's didFinishLaunchingWithOptions function.

Can you send local notifications while app is in background?

Notifications could be created at any moment (on Foreground, Background or even when the application is terminated/killed).

How do I show notification when an app is in foreground flutter?

Foreground and Notification messages Notification messages which arrive while the application is in the foreground will not display a visible notification by default, on both Android and iOS. It is, however, possible to override this behavior: On Android, you must create a "High Priority" notification channel.

What is the difference between local notification and push notification?

The essential difference between local notifications and push notifications is simple: Local notifications are scheduled by an app locally and are delivered by the same device. Push notifications are sent by a remote server (its provider) which sends these notifications to devices on which the app is installed.


2 Answers

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

enter image description here

enter image description here

like image 135
Rajan Maheshwari Avatar answered Sep 29 '22 12:09

Rajan Maheshwari


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.

like image 31
Derek Soike Avatar answered Sep 29 '22 12:09

Derek Soike