Swift push notifications delegate debug mode behavior - ios

I have APNS connected to my app.
The problem is in different behavior of system delegate didReceiveRemoteNotification. It is working properly only when the debugger is attached to the app, otherwise, it is not called when the app is in the background state. For example, the delegate is called if test phone is connected to the mac via USB cable and app is being debugged. Right after cable disconnection delegate is not called anymore.
The question is how app state (debugged or not) influence on didReceiveRemoteNotification behavior. (both IOS 10 and 11)
To detect delegate call I make backend requests and I'm sure there is no problem with call detection.

I had the same problem, spent a lot of time looking for a solution. I found a workaround mentioned in the Apple forums.
Make the class where you handle the push notifications a delegate of UNUserNotificationCenter
if #available(iOS 10.0, *) {
UNUserNotificationCenter.current().delegate = self
}
and then implement the willPresent notification: UNNotification method
#available(iOS 10.0, *)
extension APNSService: UNUserNotificationCenterDelegate {
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
Log.debug?.message("Received push in foreground through UserNotificationCenter, calling Inbox.incrementalSync")
...
completionHandler([])
}
}

Related

Unable to trigger didReceive notification delegate when you bring the app from background to foreground

I have implemented push notification for ios10. Tapping on the notification alert would trigger "didReceive" delegate, were i save the notification in coredata or silent notification if i m in foreground. The problem is if i receive a stack of notification in background and When i bring my app to foreground from background, Is there a possibility to call "didReceive" delegate or any other push notification delegate were i could sync my items to coredata.
Note
I don't want to sync(didReceive or any delegate) the items in background using silent notification nor tapping on the alert. It should sync automatically the stack of push notification when i bring the app to foreground
func handleInboxNotification(didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {
if let inboxValue = userInfo["inbox"] as? String, let value = inboxValue.boolValue(), value {
let mappedMessage = MessageCenterSDK.shared.constructReorderedDictionary(userInfo: userInfo)
MessageCenterDataManager.shared.synchronize(messages: mappedMessage)
messageCenterDelegate?.didFindNewMessages(hasNewMessages: true)
}
}
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: #escaping () -> Void) {
/// Handle outbound remote
handleInboxNotification(didReceiveRemoteNotification: response.notification.request.content.userInfo)
completionHandler()
}
I was facing the same issue, but my target was for iOS 13 & I'm using BGTaskScheduler to fetch data from the server in the background as well in terminated state.
I too want to trigger the notification when the app is in background. But not tapped but that seems to be not possible so we have changed our implementation by enabling background mode and it worked for me.
Hope it also helps.
For more reference on BGTaskScheduler, https://developer.apple.com/documentation/backgroundtasks/bgtaskscheduler
you need to use willpresent delegate in appDelegate
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
// Change this to your preferred presentation option
completionHandler([])
}
This delegate is called when a notification comes in foreground

UNUserNotificationCenterDelegate didReceive is not getting triggered in iOS with Flutter App

I have setup push notifications using APNS for iOS (Using Swift) in the flutter App. didReceiveRemoteNotification is getting triggered when the app receives a push notification from AWS Pinpoint. But none of the other methods are getting triggered when the user taps the notification. Once I handle the user action on the push notification, I can call a scheme using openUrl to specific route on the app.
I have tried by disabling/enabling background modes in the capabilities in the Xcode. Also verified that push notifications are turned on in the capabilities. Pinpoint uses APNS to send the notification to iOS and Firebase to send the notification to Android which is working fine.
Also tried with iOS target version as 10.0, 11.0 and 12.0
UNUserNotificationCenter.current().delegate = self
is declared in didFinishLaunchingWithOptions and imported UserNotifications
When I tap the push notification, this is getting printed in the console:
Warning: UNUserNotificationCenter delegate received call to -userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler: but the completion handler was never called.
Payload from pinpoint:
[AnyHashable("aps"): {
alert = {
body = "BODY";
title = "TITLE";
};
badge = 0;
"content-available" = 1;
"mutable-content" = 0;
sound = default;
}]
Code,
extension AppDelegate: UNUserNotificationCenterDelegate {
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
let userInfo = notification.request.content.userInfo
// Print full message.
print(userInfo)
// Change this to your preferred presentation option
completionHandler([])
}
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: #escaping () -> Void) {
let userInfo = response.notification.request.content.userInfo
// Print full message.
print(userInfo)
completionHandler()
}
}
didReceive is expected to get triggered when the user taps on the push notification which is not happening in my case.
Can anyone help me on how to trigger when the user taps the push notification?
I was facing a similar problem. iOS swift delegate methods were not triggered. It appears that the methods must have been declared public.
Just replace
func userNotificationCenter
with
public func userNotificationCenter
Maybe it will helps someone...
Have you set center's delegate property?
center.delegate = self
where self is AppDelegate.

iOS How to display local notification in foreground?

Is there a way to post and show local notifications in the foreground?
If not, is there a way to "fake it"?
I need to make an iOS appear like an Android app, which does have notifications in the foreground.
For iOS 10 and next you can use UNUserNotificationCenterDelegate and see this post for more information. If you app run on 8 or 9 ios you should use 3d party libs (you can search)
Sample:
Add it to your delegate methods in the AppDelegate and conform to this protocol - UNUserNotificationCenterDelegate
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler([.alert,.badge])
}

Swift: Getting Data from Remote notification

I have a messaging app, which gets data from server through push notification.
In the following image, you can see the process and also check where it gets faulted:
I have researched a lot about this problem but not getting a universal solution.
One solution I get is to use silent notification , discussed Here , to get data before it is shown and save it. But I didn't find how to show notification from app delegate once I received silent notification.
Kindly correct me if I am conceptually wrong somewhere.
Update:
One of problem is that the application:didReceiveRemoteNotification:fetchCompletionHandler: is only called when
app is in foreground
user clicks the notification
But when user doesn't click the notification, application:didReceiveRemoteNotification:fetchCompletionHandler: is not called, and I can't find a way to save the data, that is present in notification.
Your question is "To get data from Remote notification while the App is in foreground" if im correct, You can use these two methods to get data from Remote notifications for background and foreground app modes.
// Notification will present call back
#available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler([.alert, .sound, .badge])
// Handle your data here
print("Notification data: \(notification.request.content.userInfo)")
}
#available(iOS 10.0, *)
// Notification interaction response call back
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: #escaping () -> Void) {
// Handle your data here
print("Notification data: \(response.notification.request.content.userInfo)")
}
There are two cases:
Background
Closed State
If the app is in Background State, you have to enable Background Fetch, then this method will be called when the app is in Background application:didReceiveRemoteNotification:fetchCompletionHandler:
When the app is closed or killed by the user the above method not gonna work, for that you can use the VoIP technique.
didReceiveIncomingPushWithPayload method will be called whenever Remote Notification arrives
You can find more details about VoIP here

Push Notifications in iOS 11

Before iOS 11 , when the app receive a notification while running in the foreground , the notification will not appear unless using a custom view to show it.
Is the way we handle the received push notifications while app is running in the foreground changed in iOS 11?
Try this in Appdelegate class
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler(.alert)
}
this is the delegate calls when app is in foreground and if you want to show alert as well then add .alert in completionHandler.
It is added in iOS 10 onwards
Further Ref : Silent pushes not delivered to the app on iOS 11

Resources