Closed jcloquell closed 1 month ago
This is an ios 18 bug.
https://forums.developer.apple.com/forums/thread/762126
My suggestion (and also the feedback from Apple) : use the identifier fields to implement an app filter and skip the duplicated events.
import { Notification } from "react-native-notifications"
import { Platform } from "react-native"
export interface PushNotificationRegistry {
shouldFilterNotification(notification: Notification): Boolean
clear(): void
}
class IdBasedFilterPushRegistry implements PushNotificationRegistry {
private ids: Array<string>
private currentIndex = 0
private capacity: number
constructor(capacity: number = 10) {
this.capacity = capacity
this.ids = []
}
shouldFilterNotification(notification: Notification): Boolean {
if(!notification || !notification.identifier){
return false
}
const alreadyConsumed = !this.isIdentifierAlreadyPresent(notification.identifier)
this.storeIdAsConsumed(notification.identifier)
return alreadyConsumed
}
clear(): void {
this.currentIndex = 0
this.ids = []
}
private storeIdAsConsumed(identifier: string) {
// use a circular array approach to prevent memory increase
this.ids[this.currentIndex] = identifier
this.currentIndex = (this.currentIndex + 1) % this.capacity
}
private isIdentifierAlreadyPresent(id: string) {
return this.ids.find(item => item == id)
}
}
class NoopIdFilter implements PushNotificationRegistry {
shouldFilterNotification(notification: Notification): Boolean {
return false;
}
clear(): void {
}
}
export function createDefaultNotificationRegistry(enableIdFilter: Boolean = false): PushNotificationRegistry {
return enableIdFilter ? new IdBasedFilterPushRegistry() : new NoopIdFilter()
}
Usage (on foreground events:
const shouldFilter:Boolean = Platform.OS === 'ios' && parseInt(Platform.Version as string, 10) >= 18;
const registry = createDefaultNotificationRegistry(shouldFilter)
...
const notificationReceivedForegroundCallback = Notifications.events().registerNotificationReceivedForeground((notification: Notification, completion: (response: NotificationCompletion) => void) => {
if(registry.shouldFilterNotification(notification)){
console.log(">>> Blocked by app filter logic")
....
return;
}
processNotification(....)
}
Thanks a lot for the heads up @EnricoMazzu! We were already implementing a similar workaround on our side 👍 I'll close the issue then, as it's on Apple's hands to fix it.
We noticed that since the recent iOS 18 update, the foreground notification event is being fired twice.
Notifications.events().registerNotificationReceivedForeground
callback gets called one time initially, when receiving the actual push notification, and then it's called again after exactly 30 seconds have passed.This only happens on iOS devices running iOS 18, it seems to work fine on Android and older iOS versions.