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 invokeremoveObserver(_:)
orremoveObserver(_:name:object:)
before any object specified byaddObserver(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
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
Repeating Local Notifications for Specific Days of Week (Swift 3 iOS 10)
How to Cache Resources Loaded in an iPhone Uiwebview
What's Always_Embed_Swift_Standard_Libraries with Cocoapods, Swift 3 and Xcode 8
Ios5 Nsurlconnection Methods Deprecated
Find Facebook Sdk Version on iOS
Black Screen After Presenting Modal View Controller in Current Context from Uitabbarcontroller
Swapping Child Views in a Container View
How to Cast an Nsmutablearray to a Swift Array of a Specific Type
Ios: Determine If Device Language Is Right to Left (Rtl)
iOS Playground Doesn't Show UI Preview
Firebase Dynamic Link Not Opening the App iOS
Swift - Instantiating a Navigation Controller Without Storyboards in App Delegate
iOS Steps to Create Custom Uitableviewcell with Xib File