-
Notifications
You must be signed in to change notification settings - Fork 23
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: differentiate every push event handler installed in app #743
Conversation
https://linear.app/customerio/issue/MBL-383/[bug]-customer-unable-to-handle-push-notification-event-on-ios-with In a Flutter app, when `PushEventHandlerProxy.addPushEventHandler` is called, `String(describing:)` is generating a non-unique String which results in only 1 entry existing in the `nestedDelegates` entry. This results in the SDK only being aware of 1 push event handler even if the iOS app has N number installed. Testing * In Flutter sample app, install CIO SDK, FlutterFire, and set `UNNotificationCenterDelegate.current().delegate = self` for the host app to also handle pushes. Set a Xcode breakpoint in `PushEventHandlerProxy.addPushEventHandler` and check what key String is generated. After this PR, the key is unique. * The automated test suite already contains a test that should be catching this. Keeping this PR as a draft while I determine why that happened and get it fixed to prevent scenarios like this again.
Sample app builds 📱Below you will find the list of the latest versions of the sample apps. It's recommended to always download the latest builds of the sample apps to accurately test the pull request.
|
It passes before and after. But this change will make it better.
@@ -3,7 +3,7 @@ import Foundation | |||
import SharedTests | |||
import XCTest | |||
|
|||
class PushEventHandlerProxyTest: UnitTest { | |||
class PushEventHandlerProxyTest: IntegrationTest { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only changed so the class had access to the new getNewPushEventHandler()
function. Should have no effect on the tests besides that.
@@ -12,13 +12,47 @@ class PushEventHandlerProxyTest: UnitTest { | |||
proxy = PushEventHandlerProxyImpl() | |||
} | |||
|
|||
// MARK: addPushEventHandler |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These new tests catch the bug that this PR fixes.
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## v2 #743 +/- ##
=====================================
Coverage ? 57.69%
=====================================
Files ? 132
Lines ? 3806
Branches ? 0
=====================================
Hits ? 2196
Misses ? 1610
Partials ? 0 ☔ View full report in Codecov by Sentry. |
@@ -120,6 +120,10 @@ public struct UNNotificationWrapper: PushNotification { | |||
class UNUserNotificationCenterDelegateWrapper: PushEventHandler { | |||
private let delegate: UNUserNotificationCenterDelegate | |||
|
|||
var identifier: String { | |||
String(describing: delegate) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By returning the instance description of the nested delegate, this is what will uniquely identify UNUserNotificationCenterDelegateWrapper
instances from 1 another. Since UNUserNotificationCenterDelegateWrapper
is just a wrapper, it's the nested delegate that we really care about.
@@ -21,6 +21,10 @@ class IOSPushEventListener: PushEventHandler { | |||
self.logger = logger | |||
} | |||
|
|||
var identifier: String { | |||
"Cio.iOSPushEventListener" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The CIO SDK has it's own PushEventHandler
instance so we must add the new protocol identifier
getter.
This string should uniquely identify the CIO SDK from other push click handlers installed in the app.
@@ -27,7 +27,7 @@ class PushEventHandlerProxyImpl: PushEventHandlerProxy { | |||
public static let shared = PushEventHandlerProxyImpl() | |||
|
|||
// Use a map so that we only save 1 instance of a given handler. | |||
@Atomic private var nestedDelegates: [String: PushEventHandler] = [:] | |||
@Atomic var nestedDelegates: [String: PushEventHandler] = [:] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
made internal
for tests to access
@@ -37,7 +37,7 @@ class PushEventHandlerProxyImpl: PushEventHandlerProxy { | |||
} | |||
|
|||
func addPushEventHandler(_ newHandler: PushEventHandler) { | |||
nestedDelegates[String(describing: newHandler)] = newHandler | |||
nestedDelegates[newHandler.identifier] = newHandler |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The bug fix.
At runtime, multiple UNUserNotificationCenterDelegateWrapper
instances will call this function. Using identifier
makes sure that each handler is uniquely identified.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
added do not merge label until this is resolved |
## [2.13.2](2.13.1...2.13.2) (2024-06-21) ### Bug Fixes * differentiate every push event handler installed in app ([#743](#743)) ([c3573fc](c3573fc))
https://linear.app/customerio/issue/MBL-383/[bug]-customer-unable-to-handle-push-notification-event-on-ios-with (This PR is identical to the one merged into v2: #743) Summary of bug: The iOS SDK had a bug where it was only able to store 1 3rd party push click handing SDK and ignore others that were installed. After this fix, all 3rd party SDKs installed in the app are called for push events in the app.
https://linear.app/customerio/issue/MBL-383/[bug]-customer-unable-to-handle-push-notification-event-on-ios-with
At runtime when
PushEventHandlerProxy.addPushEventHandler
is called, the given push event handler will overrwrite any previously added push event handlers. This results in the SDK only being aware of 1 push event handler even if the iOS app has N number installed.Testing
UNNotificationCenterDelegate.current().delegate = self
inAppDelegate
for the host app to also handle pushes. This reproduces the bug because we now have at least 2 other push click handlers besides the CIO SDK installed. Set a Xcode breakpoint inPushEventHandlerProxy.addPushEventHandler
and check what dictionary key is generated.PushEventHandlerProxy.addPushEventHandler
function.