-
Notifications
You must be signed in to change notification settings - Fork 263
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1091 from OneSignal/fix/swizzling_not_calling_for…
…warding_target [Fix] swizzling not forwarding with apps that use UIApplicationDelegateAdaptor
- Loading branch information
Showing
12 changed files
with
523 additions
and
127 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
38 changes: 38 additions & 0 deletions
38
iOS_SDK/OneSignalSDK/OneSignalCore/Source/SwizzlingForwarder.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
#import <Foundation/Foundation.h> | ||
|
||
NS_ASSUME_NONNULL_BEGIN | ||
|
||
/** | ||
Use this in your swizzled methods implementations to ensure your swizzling | ||
does not create side effects. | ||
This is done by checking if there was an existing implementations and also if | ||
the object has a forwardingTargetForSelector: setup. | ||
*/ | ||
@interface SwizzlingForwarder : NSObject | ||
/** | ||
Constructor to setup this instance so you can call invokeWithArgs latter | ||
to forward the call onto the correct selector and object so you swizzling does | ||
create any cause side effects. | ||
@param object Your object, normally you should pass in self. | ||
@param yourSelector Your named selector. | ||
@param originalSelector The original selector, the one you would call if | ||
swizzling was out of the picture. | ||
@return Always returns an instance. | ||
*/ | ||
-(instancetype)initWithTarget:(id)object | ||
withYourSelector:(SEL)yourSelector | ||
withOriginalSelector:(SEL)originalSelector; | ||
|
||
/** | ||
Optionally call before invokeWithArgs to know it will execute anything. | ||
*/ | ||
-(BOOL)hasReceiver; | ||
|
||
/** | ||
Must call this to call in your swizzled method somewhere to ensure the | ||
original code is still run. | ||
*/ | ||
-(void)invokeWithArgs:(NSArray*)args; | ||
@end | ||
|
||
NS_ASSUME_NONNULL_END |
60 changes: 60 additions & 0 deletions
60
iOS_SDK/OneSignalSDK/OneSignalCore/Source/SwizzlingForwarder.m
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
#import "SwizzlingForwarder.h" | ||
|
||
@implementation SwizzlingForwarder { | ||
id targetObject; | ||
SEL targetSelector; | ||
} | ||
|
||
-(instancetype)initWithTarget:(id)object | ||
withYourSelector:(SEL)yourSelector | ||
withOriginalSelector:(SEL)originalSelector { | ||
self = [super init]; | ||
|
||
// If the class had a pre-existing selector | ||
if ([object respondsToSelector:yourSelector]) { | ||
targetObject = object; | ||
targetSelector = yourSelector; | ||
} | ||
else { | ||
id forwardingTarget = [object forwardingTargetForSelector:originalSelector]; | ||
// If there is a forwarding object and ensuring it does have the selector | ||
// The most common case for this is a SwiftUI app with | ||
// @UIApplicationDelegateAdaptor | ||
if (forwardingTarget && [forwardingTarget respondsToSelector:originalSelector]) { | ||
targetObject = forwardingTarget; | ||
targetSelector = originalSelector; | ||
} | ||
} | ||
|
||
return self; | ||
} | ||
|
||
-(BOOL)hasReceiver { | ||
return targetObject != nil; | ||
} | ||
|
||
+(void)callSelector:(SEL)selector | ||
onObject:(id)object | ||
withArgs:(NSArray*)args { | ||
NSMethodSignature *methodSignature = [object methodSignatureForSelector:selector]; | ||
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature]; | ||
[invocation setSelector:selector]; | ||
[invocation setTarget:object]; | ||
for(int i = 0; i < methodSignature.numberOfArguments - 2; i++) { | ||
id argv = [args objectAtIndex:i]; | ||
[invocation setArgument:&argv atIndex:i + 2]; | ||
} | ||
|
||
[invocation invoke]; | ||
} | ||
|
||
-(void)invokeWithArgs:(NSArray*)args { | ||
if (!targetObject) | ||
return; | ||
|
||
[SwizzlingForwarder | ||
callSelector:targetSelector | ||
onObject:targetObject | ||
withArgs:args]; | ||
} | ||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.