From f7132e19c1f034d96038467943ea3bf59d018f11 Mon Sep 17 00:00:00 2001 From: Marat Al Date: Sun, 28 Jul 2024 20:24:06 +0200 Subject: [PATCH 1/4] Removed `registerForRemoteNotifications` call since it's done on the cocoa side. --- ios/Classes/AblyFlutter.m | 1 - 1 file changed, 1 deletion(-) diff --git a/ios/Classes/AblyFlutter.m b/ios/Classes/AblyFlutter.m index d02602b20..46c50398a 100644 --- a/ios/Classes/AblyFlutter.m +++ b/ios/Classes/AblyFlutter.m @@ -801,7 +801,6 @@ -(void)reset { } - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - [[UIApplication sharedApplication] registerForRemoteNotifications]; // Check if application was launched from a notification tap. // https://stackoverflow.com/a/21611009/7365866 From 25ef834e179fc60b757b8e0b7b48762714dbc7f0 Mon Sep 17 00:00:00 2001 From: Marat Al Date: Sun, 28 Jul 2024 20:26:03 +0200 Subject: [PATCH 2/4] Removed unnecessary push token handling. Token is requested by ably-cocoa and received by flutter, which sends it to ably via the first available `ARTRealtime` object. All instances have the same value for the `device.push` property, since the `device` itself is stored in a static variable. --- ios/Classes/AblyFlutter.m | 28 ++-------------------------- ios/Classes/AblyInstanceStore.h | 4 +--- ios/Classes/AblyInstanceStore.m | 21 +++++++++++---------- 3 files changed, 14 insertions(+), 39 deletions(-) diff --git a/ios/Classes/AblyFlutter.m b/ios/Classes/AblyFlutter.m index 46c50398a..cdbdfcc78 100644 --- a/ios/Classes/AblyFlutter.m +++ b/ios/Classes/AblyFlutter.m @@ -76,14 +76,6 @@ -(void)reset; ARTRest *const rest = [[ARTRest alloc] initWithOptions:options.clientOptions]; [instanceStore setRest:rest with: handle]; - NSData *const apnsDeviceToken = ably.instanceStore.didRegisterForRemoteNotificationsWithDeviceToken_deviceToken; - NSError *const error = ably.instanceStore.didFailToRegisterForRemoteNotificationsWithError_error; - if (apnsDeviceToken != nil) { - [ARTPush didRegisterForRemoteNotificationsWithDeviceToken:apnsDeviceToken rest:rest]; - } else if (error != nil) { - [ARTPush didFailToRegisterForRemoteNotificationsWithError:error rest:rest]; - } - result(handle); }; @@ -262,19 +254,6 @@ -(void)reset; } ARTRealtime *const realtime = [[ARTRealtime alloc] initWithOptions:options.clientOptions]; [instanceStore setRealtime:realtime with:handle]; - - // Giving Ably client the deviceToken registered at device launch (didRegisterForRemoteNotificationsWithDeviceToken). - // This is not an ideal solution. We save the deviceToken given in didRegisterForRemoteNotificationsWithDeviceToken and the - // error in didFailToRegisterForRemoteNotificationsWithError and pass it to Ably in the first client that is first created. - // Ideally, the Ably client doesn't need to be created, and we can pass the deviceToken to Ably like in Ably Java. - // This is similarly repeated for in _createRest - NSData *const apnsDeviceToken = ably.instanceStore.didRegisterForRemoteNotificationsWithDeviceToken_deviceToken; - NSError *const error = ably.instanceStore.didFailToRegisterForRemoteNotificationsWithError_error; - if (apnsDeviceToken != nil) { - [ARTPush didRegisterForRemoteNotificationsWithDeviceToken:apnsDeviceToken realtime:realtime]; - } else if (error != nil) { - [ARTPush didFailToRegisterForRemoteNotificationsWithError:error realtime:realtime]; - } result(handle); }; @@ -813,16 +792,13 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( } #pragma mark - Push Notifications Registration - UIApplicationDelegate -/// Save the deviceToken provided so we can pass it to the first Ably client which gets created, in createRealtime or createRest. + -(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { - // Set deviceToken on all existing Ably clients, and a property which used for all future Ably clients. [_instanceStore didRegisterForRemoteNotificationsWithDeviceToken: deviceToken]; } -/// Save the error if it occurred during APNs device registration provided so we can pass it to the first Ably client which gets created, in createRealtime or createRest. - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error { - // This error will be used when the first Ably client is made. - _instanceStore.didFailToRegisterForRemoteNotificationsWithError_error = error; + [_instanceStore didFailToRegisterForRemoteNotificationsWithError:error]; } - (BOOL)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { diff --git a/ios/Classes/AblyInstanceStore.h b/ios/Classes/AblyInstanceStore.h index 8af0edbc1..c2164ce8f 100644 --- a/ios/Classes/AblyInstanceStore.h +++ b/ios/Classes/AblyInstanceStore.h @@ -27,9 +27,7 @@ NS_ASSUME_NONNULL_BEGIN -(void) didRegisterForRemoteNotificationsWithDeviceToken:(NSData *const) deviceToken; -@property(nonatomic, nullable) NSData * didRegisterForRemoteNotificationsWithDeviceToken_deviceToken; - -@property(nonatomic, nullable) NSError * didFailToRegisterForRemoteNotificationsWithError_error; +-(void)didFailToRegisterForRemoteNotificationsWithError:(NSError *const)error; -(void)reset; diff --git a/ios/Classes/AblyInstanceStore.m b/ios/Classes/AblyInstanceStore.m index 7ef35ab4d..99ced5c49 100644 --- a/ios/Classes/AblyInstanceStore.m +++ b/ios/Classes/AblyInstanceStore.m @@ -65,20 +65,21 @@ -(ARTPaginatedResult *) getPaginatedResult:(NSNumber *const) handle { return _paginatedResults[handle]; } -// Set device token on all existing clients --(void) didRegisterForRemoteNotificationsWithDeviceToken:(NSData *const) deviceToken { - _didRegisterForRemoteNotificationsWithDeviceToken_deviceToken = deviceToken; - - for (id restHandle in _restInstances) { - ARTRest *const rest = _restInstances[restHandle]; - [ARTPush didRegisterForRemoteNotificationsWithDeviceToken:deviceToken rest:rest]; - } - for (id realtimeHandle in _realtimeInstances) { - ARTRealtime *const realtime = _realtimeInstances[realtimeHandle]; +// Set device token for the first created realtime object, device of which is available for others, because it's static +-(void)didRegisterForRemoteNotificationsWithDeviceToken:(NSData *const)deviceToken { + ARTRealtime *const realtime = _realtimeInstances.allValues.firstObject; + if (realtime) { [ARTPush didRegisterForRemoteNotificationsWithDeviceToken:deviceToken realtime:realtime]; } } +-(void)didFailToRegisterForRemoteNotificationsWithError:(NSError *const)error { + ARTRealtime *const realtime = _realtimeInstances.allValues.firstObject; + if (realtime) { + [ARTPush didFailToRegisterForRemoteNotificationsWithError:error realtime:realtime]; + } +} + -(void)reset { for (ARTRealtime *const r in _realtimeInstances.allValues) { [r close]; From 18d12079312fec8bf63e8c869ba7d3b8aa24e67d Mon Sep 17 00:00:00 2001 From: Marat Al Date: Sat, 10 Aug 2024 17:21:37 +0200 Subject: [PATCH 3/4] Removed all push handling from instance store. Made `didRegisterForRemoteNotificationsWithDeviceToken` on a proper instance of the realtime/rest that called push activation. --- ios/Classes/AblyFlutter.m | 24 +++++++++++++++++++++--- ios/Classes/AblyInstanceStore.h | 4 ---- ios/Classes/AblyInstanceStore.m | 15 --------------- ios/Classes/handlers/PushHandlers.swift | 6 ++++++ 4 files changed, 27 insertions(+), 22 deletions(-) diff --git a/ios/Classes/AblyFlutter.m b/ios/Classes/AblyFlutter.m index cdbdfcc78..df9630d72 100644 --- a/ios/Classes/AblyFlutter.m +++ b/ios/Classes/AblyFlutter.m @@ -793,12 +793,30 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( #pragma mark - Push Notifications Registration - UIApplicationDelegate --(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { - [_instanceStore didRegisterForRemoteNotificationsWithDeviceToken: deviceToken]; +- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { + ARTRealtime *const realtime = [_instanceStore realtimeFrom:PushHandlers.pushActivatorHandle]; + if (realtime) { + [ARTPush didRegisterForRemoteNotificationsWithDeviceToken:deviceToken realtime:realtime]; + } + else { + ARTRest *const rest = [_instanceStore restFrom:PushHandlers.pushActivatorHandle]; + if (rest) { + [ARTPush didRegisterForRemoteNotificationsWithDeviceToken:deviceToken rest:rest]; + } + } } - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error { - [_instanceStore didFailToRegisterForRemoteNotificationsWithError:error]; + ARTRealtime *const realtime = [_instanceStore realtimeFrom:PushHandlers.pushActivatorHandle]; + if (realtime) { + [ARTPush didFailToRegisterForRemoteNotificationsWithError:error realtime:realtime]; + } + else { + ARTRest *const rest = [_instanceStore restFrom:PushHandlers.pushActivatorHandle]; + if (rest) { + [ARTPush didFailToRegisterForRemoteNotificationsWithError:error rest:rest]; + } + } } - (BOOL)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { diff --git a/ios/Classes/AblyInstanceStore.h b/ios/Classes/AblyInstanceStore.h index c2164ce8f..4567f2a83 100644 --- a/ios/Classes/AblyInstanceStore.h +++ b/ios/Classes/AblyInstanceStore.h @@ -25,10 +25,6 @@ NS_ASSUME_NONNULL_BEGIN -(ARTPaginatedResult *) getPaginatedResult:(NSNumber *const) handle; --(void) didRegisterForRemoteNotificationsWithDeviceToken:(NSData *const) deviceToken; - --(void)didFailToRegisterForRemoteNotificationsWithError:(NSError *const)error; - -(void)reset; @end diff --git a/ios/Classes/AblyInstanceStore.m b/ios/Classes/AblyInstanceStore.m index 99ced5c49..fbf97a812 100644 --- a/ios/Classes/AblyInstanceStore.m +++ b/ios/Classes/AblyInstanceStore.m @@ -65,21 +65,6 @@ -(ARTPaginatedResult *) getPaginatedResult:(NSNumber *const) handle { return _paginatedResults[handle]; } -// Set device token for the first created realtime object, device of which is available for others, because it's static --(void)didRegisterForRemoteNotificationsWithDeviceToken:(NSData *const)deviceToken { - ARTRealtime *const realtime = _realtimeInstances.allValues.firstObject; - if (realtime) { - [ARTPush didRegisterForRemoteNotificationsWithDeviceToken:deviceToken realtime:realtime]; - } -} - --(void)didFailToRegisterForRemoteNotificationsWithError:(NSError *const)error { - ARTRealtime *const realtime = _realtimeInstances.allValues.firstObject; - if (realtime) { - [ARTPush didFailToRegisterForRemoteNotificationsWithError:error realtime:realtime]; - } -} - -(void)reset { for (ARTRealtime *const r in _realtimeInstances.allValues) { [r close]; diff --git a/ios/Classes/handlers/PushHandlers.swift b/ios/Classes/handlers/PushHandlers.swift index 7ffdc13ef..64e917266 100644 --- a/ios/Classes/handlers/PushHandlers.swift +++ b/ios/Classes/handlers/PushHandlers.swift @@ -2,12 +2,17 @@ import Foundation import UserNotifications public class PushHandlers: NSObject { + + @objc + public static var pushActivatorHandle: NSNumber? + @objc public static var pushNotificationTapLaunchedAppFromTerminatedData: Dictionary? = nil; @objc public static let activate: FlutterHandler = { ably, call, result in if let push = getPush(instanceStore: ably.instanceStore, call: call, result: result) { + pushActivatorHandle = (call.arguments as! AblyFlutterMessage).handle PushActivationEventHandlers.getInstance(methodChannel: ably.channel).flutterResultForActivate = result push.activate() } else { @@ -18,6 +23,7 @@ public class PushHandlers: NSObject { @objc public static let deactivate: FlutterHandler = { ably, call, result in if let push = getPush(instanceStore: ably.instanceStore, call: call, result: result) { + pushActivatorHandle = nil PushActivationEventHandlers.getInstance(methodChannel: ably.channel).flutterResultForDeactivate = result push.deactivate() } else { From 9259fc9eb7ff89ddea9c9555ff5cb09b0d87c389 Mon Sep 17 00:00:00 2001 From: Marat Al Date: Sat, 10 Aug 2024 17:40:16 +0200 Subject: [PATCH 4/4] Empty handle check. --- ios/Classes/AblyFlutter.m | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ios/Classes/AblyFlutter.m b/ios/Classes/AblyFlutter.m index df9630d72..53e8e977e 100644 --- a/ios/Classes/AblyFlutter.m +++ b/ios/Classes/AblyFlutter.m @@ -794,6 +794,8 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( #pragma mark - Push Notifications Registration - UIApplicationDelegate - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { + if (PushHandlers.pushActivatorHandle == nil) + return; ARTRealtime *const realtime = [_instanceStore realtimeFrom:PushHandlers.pushActivatorHandle]; if (realtime) { [ARTPush didRegisterForRemoteNotificationsWithDeviceToken:deviceToken realtime:realtime]; @@ -807,6 +809,8 @@ - (void)application:(UIApplication *)application didRegisterForRemoteNotificatio } - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error { + if (PushHandlers.pushActivatorHandle == nil) + return; ARTRealtime *const realtime = [_instanceStore realtimeFrom:PushHandlers.pushActivatorHandle]; if (realtime) { [ARTPush didFailToRegisterForRemoteNotificationsWithError:error realtime:realtime];