diff --git a/GoogleUtilitiesMulticastAppDelegate.podspec b/GoogleUtilitiesMulticastAppDelegate.podspec index 22245a42..d25605eb 100644 --- a/GoogleUtilitiesMulticastAppDelegate.podspec +++ b/GoogleUtilitiesMulticastAppDelegate.podspec @@ -22,9 +22,9 @@ Pod::Spec.new do |s| watchos_deployment_target = '6.0' s.ios.deployment_target = ios_deployment_target - # s.osx.deployment_target = osx_deployment_target - # s.tvos.deployment_target = tvos_deployment_target - # s.watchos.deployment_target = watchos_deployment_target + s.osx.deployment_target = osx_deployment_target + s.tvos.deployment_target = tvos_deployment_target + s.watchos.deployment_target = watchos_deployment_target s.cocoapods_version = '>= 1.4.0' s.prefix_header_file = false diff --git a/GoogleUtilitiesMulticastAppDelegate/Sources/GULMulticastAppDelegate.m b/GoogleUtilitiesMulticastAppDelegate/Sources/GULMulticastAppDelegate.m index 08208e15..9e2ff09a 100644 --- a/GoogleUtilitiesMulticastAppDelegate/Sources/GULMulticastAppDelegate.m +++ b/GoogleUtilitiesMulticastAppDelegate/Sources/GULMulticastAppDelegate.m @@ -12,7 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -#import "GoogleUtilitiesMulticastAppDelegate/Sources/Public/GoogleUtilities/GULMulticastAppDelegate.h" +#import +//#import @interface GULMulticastAppDelegate () { NSMutableArray *_interceptors; @@ -40,7 +41,7 @@ - (instancetype)initWithAppDelegate:(id)delegate { } + (id)multicastDelegate { - id appDelegate = [UIApplication sharedApplication].delegate; + id appDelegate = [GULAppDelegateSwizzler sharedApplication].delegate; if (!appDelegate) { return nil; } @@ -64,6 +65,9 @@ - (instancetype)initWithAppDelegate:(id)delegate { - (void)addInterceptorWithInterceptor:(id)interceptor { [_interceptors addObject:interceptor]; + if (!_defaultAppDelegate) { + _defaultAppDelegate = interceptor; + } } - (void)removeInterceptorWithInterceptor:(id)interceptor { @@ -71,6 +75,9 @@ - (void)removeInterceptorWithInterceptor:(id)interceptor } - (BOOL)respondsToSelector:(SEL)aSelector { + if (_defaultAppDelegate && [_defaultAppDelegate respondsToSelector:aSelector]) { + return YES; + } if ([[self class] instancesRespondToSelector:aSelector]) { return YES; } @@ -79,6 +86,7 @@ - (BOOL)respondsToSelector:(SEL)aSelector { return YES; } } + return NO; } @@ -126,7 +134,17 @@ - (void)didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { } #endif // !TARGET_OS_WATCH -#if TARGET_OS_IOS || TARGET_OS_TV +#if TARGET_OS_WATCH + +- (void)didFailToRegisterForRemoteNotificationsWithError:(NSError *)error { + for (id interceptor in _interceptors) { + if ([interceptor + respondsToSelector:@selector(didFailToRegisterForRemoteNotificationsWithError:)]) { + [interceptor didFailToRegisterForRemoteNotificationsWithError:error]; + } + } +} +#elif TARGET_OS_IOS || TARGET_OS_TV - (void)application:(GULApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error { for (id interceptor in _interceptors) { diff --git a/GoogleUtilitiesMulticastAppDelegate/Sources/GULMulticastUserNotificationCenterDelegate.m b/GoogleUtilitiesMulticastAppDelegate/Sources/GULMulticastUserNotificationCenterDelegate.m new file mode 100644 index 00000000..45be3a6f --- /dev/null +++ b/GoogleUtilitiesMulticastAppDelegate/Sources/GULMulticastUserNotificationCenterDelegate.m @@ -0,0 +1,125 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +API_AVAILABLE(ios(10.0)) +@interface GULMulticastUserNotificationCenterDelegate () { + NSMutableArray *_interceptors; + id _defaultAppDelegate; +} +@end + +@implementation GULMulticastUserNotificationCenterDelegate + +- (instancetype)init API_AVAILABLE(ios(10.0)) { + self = [super init]; + if (self) { + _interceptors = [NSMutableArray array]; + } + return self; +} + ++ (id)multicastDelegate { + if (@available(iOS 10.0, *)) { + id appDelegate = + [UNUserNotificationCenter currentNotificationCenter].delegate; + + if (!appDelegate) { + return nil; + } + if ([appDelegate conformsToProtocol:@protocol(GULMulticastNotificationProtocol)]) { + id multicastAppDelegate = + (id)appDelegate; + return multicastAppDelegate; + } + if ([appDelegate respondsToSelector:@selector(getMulticastDelegate)]) { + id multicastDelegate = + [appDelegate performSelector:@selector(getMulticastDelegate)]; + CFRetain((__bridge CFTypeRef)(multicastDelegate)); + return multicastDelegate; + } + } else { + // Fallback on earlier versions + } + return nil; +} + +- (id)getMulticastDelegate { + return self; +} + +- (void)addInterceptorWithInterceptor:(id)interceptor + API_AVAILABLE(ios(10.0)) { + [_interceptors addObject:interceptor]; +} + +- (void)removeInterceptorWithInterceptor:(id)interceptor + API_AVAILABLE(ios(10.0)) { + [_interceptors removeObject:interceptor]; +} + +- (BOOL)respondsToSelector:(SEL)aSelector { + if ([[self class] instancesRespondToSelector:aSelector]) { + return YES; + } + for (id interceptor in _interceptors) { + if (interceptor && [interceptor respondsToSelector:aSelector]) { + return YES; + } + } + return NO; +} + +- (void)setDefaultAppDelegate:(id)defaultAppDelegate + API_AVAILABLE(ios(10.0)) { + [_interceptors addObject:defaultAppDelegate]; + _defaultAppDelegate = defaultAppDelegate; +} + +- (id)forwardingTargetForSelector:(SEL)aSelector { + return _defaultAppDelegate; +} + +#pragma mark - UNUserNotificationCenterDelegate + +- (void)userNotificationCenter:(UNUserNotificationCenter *)center + willPresentNotification:(UNNotification *)notification + withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler + API_AVAILABLE(ios(10.0)) { + for (id interceptor in _interceptors) { + if ([interceptor respondsToSelector:@selector(userNotificationCenter: + willPresentNotification:withCompletionHandler:)]) { + [interceptor userNotificationCenter:center + willPresentNotification:notification + withCompletionHandler:completionHandler]; + } + } +} + +- (void)userNotificationCenter:(UNUserNotificationCenter *)center + didReceiveNotificationResponse:(UNNotificationResponse *)response + withCompletionHandler:(void (^)(void))completionHandler API_AVAILABLE(ios(10.0)) { + for (id interceptor in _interceptors) { + if ([interceptor + respondsToSelector:@selector(userNotificationCenter: + didReceiveNotificationResponse:withCompletionHandler:)]) { + [interceptor userNotificationCenter:center + didReceiveNotificationResponse:response + withCompletionHandler:completionHandler]; + } + } +} + +@end diff --git a/GoogleUtilitiesMulticastAppDelegate/Sources/Public/GoogleUtilities/GULMulticastAppDelegate.h b/GoogleUtilitiesMulticastAppDelegate/Sources/Public/GoogleUtilities/GULMulticastAppDelegate.h index e59e8a40..df56e93c 100644 --- a/GoogleUtilitiesMulticastAppDelegate/Sources/Public/GoogleUtilities/GULMulticastAppDelegate.h +++ b/GoogleUtilitiesMulticastAppDelegate/Sources/Public/GoogleUtilities/GULMulticastAppDelegate.h @@ -14,7 +14,7 @@ #import -#import +#import NS_ASSUME_NONNULL_BEGIN @@ -32,8 +32,6 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)initWithAppDelegate:(id)delegate; -- (void)addInterceptorWithInterceptor:(id)delegate; - + (id)multicastDelegate; @end diff --git a/GoogleUtilitiesMulticastAppDelegate/Sources/Public/GoogleUtilities/GULMulticastUserNotificationCenterDelegate.h b/GoogleUtilitiesMulticastAppDelegate/Sources/Public/GoogleUtilities/GULMulticastUserNotificationCenterDelegate.h new file mode 100644 index 00000000..0c9cc0a6 --- /dev/null +++ b/GoogleUtilitiesMulticastAppDelegate/Sources/Public/GoogleUtilities/GULMulticastUserNotificationCenterDelegate.h @@ -0,0 +1,42 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0 || \ + __MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_10_14 || __TV_OS_VERSION_MAX_ALLOWED >= __TV_10_0 || \ + __WATCH_OS_VERSION_MAX_ALLOWED >= __WATCHOS_3_0 || TARGET_OS_MACCATALYST +#import +#endif +#import + +NS_ASSUME_NONNULL_BEGIN + +API_AVAILABLE(ios(10.0)) +@protocol GULMulticastNotificationProtocol + +- (void)addInterceptorWithInterceptor:(id)interceptor; + +- (void)removeInterceptorWithInterceptor:(id)interceptor; + +@end + +API_AVAILABLE(ios(10.0)) +@interface GULMulticastUserNotificationCenterDelegate : NSObject + +@property(nonatomic, copy) id defaultAppDelegate; + ++ (id)multicastDelegate; +@end + +NS_ASSUME_NONNULL_END