@@ -130,7 +130,7 @@ @interface UNUserNotificationCenterDelegateForInfiniteLoopWithAnotherSwizzlerTes
130130@end
131131@implementation UNUserNotificationCenterDelegateForInfiniteLoopWithAnotherSwizzlerTest
132132@end
133- @interface OtherUNNotificationLibraryASwizzler : NSObject
133+ @interface OtherUNNotificationLibraryASwizzler : UIResponder < UNUserNotificationCenterDelegate >
134134+(void )swizzleUNUserNotificationCenterDelegate ;
135135+(BOOL )selectorCalled ;
136136@end
@@ -157,7 +157,33 @@ -(void)userNotificationCenterLibraryA:(UNUserNotificationCenter *)center willPre
157157 [self userNotificationCenterLibraryA: center willPresentNotification: notification withCompletionHandler: completionHandler];
158158}
159159@end
160+ @interface OtherUNNotificationLibraryBSubClassSwizzler : OtherUNNotificationLibraryASwizzler
161+ +(void )swizzleUNUserNotificationCenterDelegate ;
162+ +(BOOL )selectorCalled ;
163+ @end
164+ @implementation OtherUNNotificationLibraryBSubClassSwizzler
160165
166+ +(BOOL )selectorCalled {
167+ return selectorCalled;
168+ }
169+
170+ +(void )swizzleUNUserNotificationCenterDelegate
171+ {
172+ swizzleExistingSelector (
173+ [UNUserNotificationCenter .currentNotificationCenter.delegate class ],
174+ @selector (userNotificationCenter:willPresentNotification:withCompletionHandler: ),
175+ [self class ],
176+ @selector (userNotificationCenterLibraryB:willPresentNotification:withCompletionHandler: )
177+ );
178+ }
179+ -(void )userNotificationCenterLibraryB : (UNUserNotificationCenter *)center willPresentNotification : (UNNotification *)notification withCompletionHandler : (void (^)(UNNotificationPresentationOptions ))completionHandler
180+ {
181+ selectorCalled = true ;
182+ // Standard basic swizzling forwarder another library may have.
183+ if ([self respondsToSelector: @selector (userNotificationCenterLibraryA:willPresentNotification:withCompletionHandler: )])
184+ [self userNotificationCenterLibraryB: center willPresentNotification: notification withCompletionHandler: completionHandler];
185+ }
186+ @end
161187
162188
163189@interface OneSignalUNUserNotificationCenterSwizzlingTest : XCTestCase
@@ -319,6 +345,41 @@ - (void)testDoubleSwizzleInfiniteLoop {
319345 [localOrignalDelegate userNotificationCenter: UNUserNotificationCenter .currentNotificationCenter willPresentNotification: [self createBasiciOSNotification ] withCompletionHandler: ^(UNNotificationPresentationOptions options) {}];
320346}
321347
348+ - (void )testNotificationCenterSubClassIsNotSwizzledTwice {
349+ // 1. Create a new delegate and assign it
350+ id myDelegate = [UNUserNotificationCenterDelegateForInfiniteLoopTest new ];
351+ UNUserNotificationCenter .currentNotificationCenter .delegate = myDelegate;
352+
353+ // 2. Create another Library's app delegate and assign it then swizzle
354+ id thierDelegate = [OtherUNNotificationLibraryASwizzler new ];
355+ UNUserNotificationCenter .currentNotificationCenter .delegate = thierDelegate;
356+ [OtherUNNotificationLibraryASwizzler swizzleUNUserNotificationCenterDelegate ];
357+
358+ // 3. Create another Library's app delegate subclass and assign it then swizzle
359+ id thierDelegateSubClass = [OtherUNNotificationLibraryBSubClassSwizzler new ];
360+ UNUserNotificationCenter .currentNotificationCenter .delegate = thierDelegateSubClass;
361+ [OtherUNNotificationLibraryBSubClassSwizzler swizzleUNUserNotificationCenterDelegate ];
362+
363+ // 4. Call something to confirm we don't get stuck in an infinite call loop
364+ id <UNUserNotificationCenterDelegate > delegate =
365+ UNUserNotificationCenter .currentNotificationCenter .delegate ;
366+ [delegate
367+ userNotificationCenter: UNUserNotificationCenter .currentNotificationCenter
368+ willPresentNotification: [self createBasiciOSNotification ]
369+ withCompletionHandler: ^(UNNotificationPresentationOptions options) {}
370+ ];
371+
372+ // 5. Ensure OneSignal's selector is called.
373+ XCTAssertEqual ([OneSignalUNUserNotificationCenterOverrider
374+ callCountForSelector: @" onesignalUserNotificationCenter:willPresentNotification:withCompletionHandler:" ], 1 );
375+
376+ // 6. Ensure other library selector is still called too.
377+ XCTAssertTrue ([OtherUNNotificationLibraryASwizzler selectorCalled ]);
378+
379+ // 7. Ensure other library subclass selector is still called too.
380+ XCTAssertTrue ([OtherUNNotificationLibraryBSubClassSwizzler selectorCalled ]);
381+ }
382+
322383- (void )testCompatibleWithOtherSwizzlerWhenSwapingBetweenNil {
323384 // 1. Create a new delegate and assign it
324385 id myAppDelegate = [UNUserNotificationCenterDelegateForInfiniteLoopWithAnotherSwizzlerTest new ];
0 commit comments