I have enabled UserNotifications in my app and it all works great, apart from a bug in the very beginning (First install). Local Notification requires to ask user for permission to send notifications and it comes as an alert on first install, where user chooses his/hers options ("Allow", "Don't Allow"). The problem is that this notification request is called in "applicationDidFinishLaunchingWithOptions" method in AppDelegate and it gets cut off by another alert, which is my LocalAuthorization(TouchID) alert initiated in viewDidLoad. Is there a way to put all those alerts in some kind of a queue, so they are fired one after another and not over each other? Or, to somehow tell viewDidLoad alert to wait for AppDelegate alert to finish showing? Any input is welcome. Thanks.
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")//here you can your alert
case "action2":
print("Action Second Tapped")//here you can your alert
default:
break
}
completionHandler()
}
}
Move UNUserNotification authorization request from AppDelegate to viewDidLoad and call other alerts in completion block.
Related
I've successfully added a StartWorkoutIntent to my watch app for when the action button is pressed, however I need to be notified when the app was opened via the intent. Apple's docs say to implement this handle function below which I have in my Extension Delegate, however when you press the action button it is never called?
func handle(startWorkout intent: INStartWorkoutIntent,
completion: #escaping (INStartWorkoutIntentResponse) -> Void) {
print("WE are called!")
// Let the app start the workout.
let response = INStartWorkoutIntentResponse(code: .continueInApp,
userActivity: nil)
completion(response)
}
This never gets called either:
func handle(_ userActivity: NSUserActivity) {
if userActivity.activityType == "Start Workout" {
print("Handle Start Workout called")
}
}
In willPresent Notification methods we receive payload when app in foreground state.
Actually I want to generate local notification from firebase push notification response and I couldn't understand which delegate methods is called when application in background and terminated state.
You should always invoke the willPresent method's completionHandler method as it is mentioned in the docs:
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler([.banner, .sound])
}
With this, you will be able to handle the notification even in backgrounded or terminated state.
Hello I am trying to display some notification datas.
In my notification I have a notification id to react deferently based on the pushed information.
I just cannot see what are those new UNNotificationPresentationOptions.
in my
userNotificationCenter(_: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void)
I have
if notification.request.content.userInfo[keyName] as? String == "someId" {
// Bla bla stuffs
if #available(iOS 14.0, *) {
completionHandler([.list, .banner, .sound])
} else {
completionHandler([.alert])
}
} else if ...
But when using [.banner] or [.list] or [.banner, .list] (without .alert) I just got nothing in foreground. In an ideal world I'd love to have the notification listed in the Notification center and display relevant information in my app (before calling completion handler).
Am I using thoses options right ?
[.list] will only show the notification in the notification center (the menu that shows when you pull down from the top)
[.banner] will only pop down a banner from the top like a normal push notification
[.list, .banner] will do both: show the banner and also make sure it's on the list.
[.alert] does essentially the same as having [.list, .banner], from what I can tell. They just added these two options to give more granular control.
I just tested this locally and it did what I expected, so if it doesn't work for you it may not be hitting those lines. Did you add some breakpoints to verify that those lines were getting hit?
The notification shows in two ways
It shows in the top menu (the menu that shows when you pull down from the top)
In the notification center list
First, [.list] - It will show in the notification centre list, not in the top menu.
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler([.list, .badge, .sound])
}
Second [.banner] - It will show in the top menu but not in the list like list
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler([.banner, .badge, .sound])
}
If you want both things list and top menu in the Notification Center then do this
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler([.banner, .list, .badge, .sound])
}
It will give you both image output.
[.alert] does essentially the same as having [.list, .banner], from what I can tell. They just added these two options to give more granular control.
If you are looking for the code or tutorial then please check my video on Local Notification :- https://www.youtube.com/watch?v=yMbujKTf0uQ&t=1480s
I am using FCM with my ios push notification. How can I navigate to a specific navigation link when the user taps the push notification. Thank you in advance for your help!
I understand that I will handle the push notification tap on this function.
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[gcmMessageIDKey] {
print("Message ID userNotificationCenterdidReceive response: \(messageID)")
}
// Print full message.
print(userInfo)
let application = UIApplication.shared
if(application.applicationState == .active){
print("user tapped the notification bar when the app is in foreground")
}
if(application.applicationState == .inactive)
{
print("user tapped the notification bar when the app is in background")
}
completionHandler()
}
I also have an #EnvironmentObject that controls which tabItem is active and which NavigationLink is open.
How can I access this EnvironmentObject on my UNNotificationResponse didReceive function?
Assuming this callback is in AppDelegate, you can make AppDelegate owner of your shared object which is used as environment object, so you have access to it and in app delegate callbacks and in scene delegate to inject into content view.
Please see my proposed approach for similar scenario in App Delegate Accessing Environment Object
After reading all the guides, and after checking hundred of articles on the internet, I'm quite sure that the method receivedBackgroundNotification is never called.
Everything works perfect, but when the app is in background, a notification is shown and this method never is called. Seems to be impossible to get it working.
Assuming all the normal operations and the basic configuration is well done and is working, what can I do to intercept and manage background push notifications with this library?
I will appreciate a lot any help.
Make sure you have the following configured:
Remote notifications background mode enabled in the target's capabilities
Background app refreshed is enabled on your test device
Assuming you are trying to use the UAPushNotificationDelegate, make sure you either have automatic setup enabled or you are forwarding all the proper methods to UA SDK.
Apple will only wake up your application if you send the push notification with content-available=1 in the payload. The option is exposed in the composer as "background processing" or you can set it in the iOS overrides when using the push api.
In Urban Airship iOS SDK v.13.4.0 if func receivedBackgroundNotification(_ notificationContent: UANotificationContent, completionHandler: #escaping (UIBackgroundFetchResult) -> Void) is not called you can handle notifications in func receivedNotificationResponse(_ notificationResponse: UANotificationResponse, completionHandler: #escaping () -> Void) if you display notifications as alerts. Remember that you should only handle the notifications with actionIdentifier == UNNotificationDefaultActionIdentifier (the user opened the app from the notification interface).
This is an example of UAPushNotificationDelegate implementation:
extension MyPushNotificationDelegate: UAPushNotificationDelegate {
public func receivedForegroundNotification(_ notificationContent: UANotificationContent, completionHandler: #escaping () -> Void) {
completionHandler()
}
public func receivedBackgroundNotification(_ notificationContent: UANotificationContent, completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
completionHandler(.newData)
}
public func receivedNotificationResponse(_ notificationResponse: UANotificationResponse, completionHandler: #escaping () -> Void) {
guard notificationResponse.actionIdentifier == UNNotificationDefaultActionIdentifier else {
completionHandler()
return
}
someFunc() {
completionHandler()
}
}
public func extend(_ options: UNNotificationPresentationOptions = [], notification: UNNotification) -> UNNotificationPresentationOptions {
[.alert, .badge, .sound]
}
}