iOS push notification banner clear action button [duplicate] - ios

This question already has answers here:
How to detect "clear" notifications
(3 answers)
Closed 4 years ago.
i want to do something when user clear notification from home screen is it possible to get trigger when user tap on clear button on push notification banner, i ended up with adding custom button on view but thats not feasible.
image is attached i want trigger when user tap on this clear action any idea ???
{
“aps” : {
“category” : “MEETING_INVITATION”
“alert” : {
“title” : “Weekly Staff Meeting”
“body” : “Every Tuesday at 2pm”
},
},
“MEETING_ID” : “123456789”,
“USER_ID” : “ABCD1234”
}
i have done this but its adding button on view like popup
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler:
#escaping () -> Void) {
// Get the meeting ID from the original notification.
let userInfo = response.notification.request.content.userInfo
let meetingID = userInfo["MEETING_ID"] as! String
let userID = userInfo["USER_ID"] as! String
// Perform the task associated with the action.
switch response.actionIdentifier {
case "ACCEPT_ACTION":
sharedMeetingManager.acceptMeeting(user: userID,
meetingID: meetingID)
break
case "DECLINE_ACTION":
sharedMeetingManager.declineMeeting(user: userID,
meetingID: meetingID)
break
// Handle other actions…
default:
break
}
// Always call the completion handler when done.
completionHandler()
}

From docs about actionIdentifier:
This parameter may contain one the identifier of one of your UNNotificationAction objects or it may contain a system-defined identifier. The system defined identifiers are UNNotificationDefaultActionIdentifier and UNNotificationDismissActionIdentifier, which indicate that the user opened the app or dismissed the notification without any further actions.
So you don’t have to use your own identifiers, use system’s.
Instead of
"ACCEPT_ACTION"
use
UNNotificationDefaultActionIdentifier
and instead of
"DECLINE_ACTION"
use
UNNotificationDismissActionIdentifier

Related

SwiftUi | Create an error message in a model or class that is available in all views

I want to create a generic api utility that I can implement in any model. Therefore, I am currently faced with the problem of outputting error messages from the model regardless of a view. The error messages are needed to trigger a "no internet" or "poor internet connection" notification.
In general, it would help me a lot, regardless of the current view, to generate error messages in different classes in order to then inform the user of a failed process.
Here is my Code so far:
func execute(requestBody: [String: Any], withCompletion completion: #escaping (Data?, Int) -> Void) {
if !CheckApiReachability().getIsApiReachable() {
//trigger error message here
}
I have now used the Notification Center to implement an event which triggers an alert in my content view.
Emmit/ Post the Notification:
let nc = NotificationCenter.default
self.nc.post(name: Notification.Name("InternetConnectionErrorAppeared"), object: nil)
Receive/ Subscribe/ Listen to the emited event and trigger something:
.onReceive(nc.publisher(for: Notification.Name("InternetConnectionErrorAppeared"))) { output in
print("-- Api call failed triggered status code event")
}

How to delete specific remote notification if app is closed or in background

My app has a chat service, when new notification is received, I want to clear the notifications between user1 and user2 except the new one.
I can do it when app is in foreground by calling:
UNUserNotificationCenter.current().getDeliveredNotifications { notifications in
print("count: \(notifications.count)")
for notif in notifications {
let nUserInfo = notif.request.content.userInfo
let nType = Int(nUserInfo[AnyHashable("type")] as! String)
if nType == type {
let notifId = notif.request.identifier
if notifId != notification.request.identifier {
center.removeDeliveredNotifications(withIdentifiers: [notif.request.identifier])
}
}
}
where type is a customValue.
How to do this when app is in background or closed by a user.
You need to turn on Background Modes capability and check Remote notifications mode. In order to delete the notification in background, you need to send a new notification with no alert, like {"aps": {"content-available": 1}, "del-id": "1234"}, where content-available means (you can check more about here Apple push service)
Include this key with a value of 1 to configure a background update notification. When this key is present, the system wakes up your app in the background and delivers the notification to its app delegate. For information about configuring and handling background update notifications, see Configuring a Background Update Notification.
and del-id will be the id of the notification you want to delete, you can use an array as well. You can put these information with together with your message notification as well.
In your AppDelegate.swift you will need to add this method to delete the notification in background. In your case, you can send the id of the notification you does not want to delete and use your method to delete all delivered notification except the one with the id you send in your last notification.
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
guard let idToDelete = userInfo["del-id"] as? String else {
completionHandler(.noData)
return
}
UNUserNotificationCenter.current().removeDeliveredNotifications(withIdentifiers: [idToDelete])
completionHandler(.noData)
}

How to change iOS notification message upon receiving?

When I push notification from OneSignal, I want to push something like
", you have received a message"
I want to replace $name in app with the username something like
notificationMessage = UserDefaults.standard.string(forKey: "username") + notificationMessage
Is it possible to override notification?
If you mean to change the alert that the System shows, then NO you can't change those. They are managed by the OS.
For foreground only:
If you have some internal alert that you'd like to pop—when the app is in foreground then you're free to do as you wish
For example you could do something like:
func userNotificationCenter(center: UNUserNotificationCenter, willPresentNotification notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
//1. extract notification data
let message = notification.request.content.body
let title = notification.request.content.title
// 2. use the message and title and change their values
// 3. use your new message and title and show your own custom alert.
// 4. I excluded the alert so you could show whatever you like yourself. But still I want to increase the badge and have sound when notification arrives...
completionHandler([.badge, .sound])
}
you can't change the request itself since it's a get only...
Having that said I don't suggest this. Your logic of this should be handled on the server you push these notifications. This should be unnecessary.

How to retrieve realm object from different function? Swift

I currently have a function that writes a realm object into the database and writes a notification. When the object is written, it is added into a uicollectionview and displayed. The function below adds the object and sets a notification based on a UIDatePicker. That code is not shown since it is a lot that doesn't pertain to the problem:
func createTaskWithDate() {
let task = Task()
task.name = textField.text!
//notification code under here
try! realm.write {
realm.add(task)
updateData()
}
I also have another function that responds to an action on a notification set. When the user taps on the notification, they are given the option to "mark as complete". When the user taps "mark as complete", I am trying to retrieve the object from the "createTaskWithDate()" method and delete it from the collection view however I'm unsure on how to retrieve that object from that method:
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
let identifier = response.actionIdentifier
let request = response.notification.request
if identifier == "complete" {
try! realm.write {
//realm.delete(task object from createTaskWithDate())
updateData()
}
}
completionHandler()
}
How could I go about doing this?
When setting up the notification, you should store the name/primary key of the object the notification is about in your notification request. You can store any information in UNMutableNotificationContent.userInfo and access it in userNotificationCenter(_:didReceive:withCompletionHandler:) by
let userInfo = response.notification.content.userInfo.
Then you can retrieve the object from Realm with the primary key stored in userInfo.
You want to create new element when your User Notification have fired or find element that already exist? If you want to find, you can query that element from data base and than delete it. You can query by date or identifier (you can implement it using User Defaults, by adding identifier field to element and increment it each time when you create new element).
For UI modification after object manipulation you can use object notifications from Realm. You can read about it here.

How to handle UNNotificationAction when app is closed?

How to handle new iOS10 Notification Action when app is closed (not in background) ?
when app is minimalized everything works fine with:
UNUserNotificationCenter.current().delegate = x
and handling it in
class x: UNUserNotificationCenterDelegate {
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Swift.Void) {
}
}
but nothing is called when app is closed and user tap action in notification... maybe i can't handle background task and i always have to launch app?
The notification action buttons handling can be done in both Extension as well as in Containing App.
When the action button is tapped, the handle first goes to the Extension and then to the Containing App if required. If Extension does not handle the notification action, the handle is passed on to the containing app.
Tapping a button launches your app (either in the foreground or
background) and gives you a chance to perform the indicated action.
Handling in extension:
func didReceive(_ response: UNNotificationResponse, completionHandler completion: #escaping (UNNotificationContentExtensionResponseOption) -> Void)
{
//You need to handle all the actions that appear with notification..
completion(.dismissAndForwardAction)
}
The completion closure takes a value of type UNNotificationContentExtensionResponseOption:
enum UNNotificationContentExtensionResponseOption : UInt
{
case doNotDismiss //the custom UI is not dismissed after handling the action
case dismiss //the custom UI is dismissed after handling the action
case dismissAndForwardAction //the custom UI is dismissed after handling the action and the control is then passed to containing app for any additional handling
}
Handling in Containing App:
extension AppDelegate : UNUserNotificationCenterDelegate
{
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void)
{
// Action handling - handling for all actions is not required
completionHandler()
}
}
For more you can refer to this(https://github.com/pgpt10/RichNotificationSample) tutorial.
Yes, it always launch the app, when user tap action in notification, button launches your app.
Some lines from apple doc:
Tapping a button launches your app (either in the foreground or background) and gives you a chance to perform the indicated action. You use this class to specify the text that is displayed in the button and the information your app needs to perform the corresponding action.
"Tapping a button launches your app (either in the foreground or background) and gives you a chance ... "
These lines appear in the doc for UIUserNotificationAction, which has been deprecated in iOS10.
The original question refers to the UNUserNotificationCenterDelegate in iOS 11.
Relevant doc: Declaring Your Actionable Notification Types
Quote from the doc:
When the user selects an action, the system launches your app in the
background and notifies the shared UNUserNotificationCenter object,
which notifies its delegate. Use your delegate object's
userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:
method to identify the selected action and provide an appropriate
response.

Resources