Triggering a Specific Action When the App Enters Foreground from a Local Notification in iOS? (Using Swift)

Triggering a specific action when the app enters foreground from a local notification in iOS? (using swift)

If I want a view controller to be notified when the app is brought back to the foreground, I might just register for the UIApplication.willEnterForegroundNotification notification (bypassing the app delegate method entirely):

class ViewController: UIViewController {

private var observer: NSObjectProtocol?

override func viewDidLoad() {
super.viewDidLoad()

observer = NotificationCenter.default.addObserver(forName: UIApplication.willEnterForegroundNotification, object: nil, queue: .main) { [unowned self] notification in
// do whatever you want when the app is brought back to the foreground
}
}

deinit {
if let observer = observer {
NotificationCenter.default.removeObserver(observer)
}
}
}

Note, in the completion closure, I include [unowned self] to avoid strong reference cycle that prevents the view controller from being deallocated if you happen to reference self inside the block (which you presumably will need to do if you're going to be updating a class variable or do practically anything interesting).

Also note that I remove the observer even though a casual reading of the removeObserver documentation might lead one to conclude is unnecessary:

If your app targets iOS 9.0 and later or macOS 10.11 and later, you don't need to unregister an observer in its dealloc method.

But, when using this block-based rendition, you really do need to remove the notification center observer. As the documentation for addObserver(forName:object:queue:using:) says:

To unregister observations, you pass the object returned by this method to removeObserver(_:). You must invoke removeObserver(_:) or removeObserver(_:name:object:) before any object specified by addObserver(forName:object:queue:using:) is deallocated.

Get local notification when App is in foreground Swift 4 iOS 11

The notification probably also fires while you app is in foreground.

Per Default, iOS does not show any UI when a notification arrives and the target app is in the foreground. It is the applications job to display the notification contents. Using UNUserNotificationCenterDelegate you can very easily display the notification as an alert. See this post for more information.

How to detect when iOS app appears in foreground, with Swift?

You can use the applicationDidBecomeActive(_:) method of your UIApplicationDelegate. You should read up on the app lifecycle. Your app delegate would then need to inform your view controller in some fashion.

Or you can register your view controller as an observer of the UIApplicationDidBecomeActive notification. Documentation for that can be found here

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

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

Sample Image

Sample Image

Get push notification while App in foreground iOS

If the application is running in the foreground, iOS won't show a notification banner/alert. That's by design. But we can achieve it by using UILocalNotification as follows

  • Check whether application is in active state on receiving a remote

    notification. If in active state fire a UILocalNotification.

    if (application.applicationState == UIApplicationStateActive ) {

    UILocalNotification *localNotification = [[UILocalNotification alloc] init];
    localNotification.userInfo = userInfo;
    localNotification.soundName = UILocalNotificationDefaultSoundName;
    localNotification.alertBody = message;
    localNotification.fireDate = [NSDate date];
    [[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
    }

SWIFT:

if application.applicationState == .active {
var localNotification = UILocalNotification()
localNotification.userInfo = userInfo
localNotification.soundName = UILocalNotificationDefaultSoundName
localNotification.alertBody = message
localNotification.fireDate = Date()
UIApplication.shared.scheduleLocalNotification(localNotification)
}

Display notification with the app in the foreground

On iOS the system does not automatically display notifications that are delivered while your app is running in the foreground.

From the documentation

If your app is in the foreground, the system delivers the notification to your app for handling.

You need to implement the userNotificationCenter(_:willPresent:withCompletionHandler:) delegate function and call the provided completion handler with the desired presentation option, probably .banner

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

You will need to establish your Notification Center delegate in an appropriate place, such as didFinishLaunching

Trigger an action when timer expires in the background

Timers will only run in the background if your app is running in the background for another reason. You will need to enable a background mode on the capabilities page. Your timer will also need to have already started when you enter the background

This may also be helpful:
https://www.raywenderlich.com/5817-background-modes-tutorial-getting-started



Related Topics



Leave a reply



Submit