-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implemented actual hooks and included new examples
- Loading branch information
1 parent
2895c7c
commit 91fb618
Showing
6 changed files
with
131 additions
and
9 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
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,33 @@ | ||
// | ||
// ASHook+BlockInsert.h | ||
// ASHookIt | ||
// | ||
// Created by Adam Szedelyi on 2017. 02. 26.. | ||
// Copyright © 2017. Adam Szedelyi. All rights reserved. | ||
// | ||
|
||
#import <ASHookIt/ASHookIt.h> | ||
|
||
@interface ASHook (BlockInsert) | ||
|
||
/** | ||
* Runs the given block on the target just before the given selector gets called. | ||
* | ||
* @param block The block that will run. | ||
* @param targetInstance The instance where you want to run the block. | ||
* @param originalSelector The original selector that will trigger the block and run after the block. | ||
* | ||
*/ | ||
+ (void)runBlock:(void (^)(__unsafe_unretained id _self))block onTarget:(id)targetInstance beforeInstanceSelector:(SEL)originalSelector; | ||
|
||
/** | ||
* Runs the given block on the target just before the given selector gets called. | ||
* | ||
* @param block The block that will run. | ||
* @param targetClass The class where you want to run the block. | ||
* @param originalSelector The original selector that will trigger the block and run after the block. | ||
* | ||
*/ | ||
+ (void)runBlock:(void (^)(__unsafe_unretained id _self))block onTarget:(id)targetClass beforeClassSelector:(SEL)originalSelector; | ||
|
||
@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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
// | ||
// ASHook+BlockInsert.m | ||
// ASHookIt | ||
// | ||
// Created by Adam Szedelyi on 2017. 02. 26.. | ||
// Copyright © 2017. Adam Szedelyi. All rights reserved. | ||
// | ||
|
||
#import "ASHook+BlockInsert.h" | ||
#import "ASHook+MethodSwizzler.h" | ||
#import <objc/runtime.h> | ||
#import <objc/message.h> | ||
|
||
@interface ASHook () | ||
|
||
+ (void)swizzle:(id)target | ||
selector:(SEL)originalSelector | ||
newSelector:(SEL)newSelector | ||
originalMethod:(Method)originalMethod | ||
newMethod:(Method)newMethod; | ||
|
||
@end | ||
|
||
@implementation ASHook (BlockInsert) | ||
|
||
#pragma mark - Public methods | ||
|
||
+ (void)runBlock:(void (^)(__unsafe_unretained id _self))block onTarget:(id)targetInstance beforeInstanceSelector:(SEL)originalSelector { | ||
id target = [targetInstance class]; | ||
Method originalMethod = class_getInstanceMethod(target, originalSelector); | ||
SEL newSelector = [self insertBlock:block onTarget:target originalSelector:originalSelector originalMethod:originalMethod]; | ||
if (newSelector) { | ||
Method newMethod = class_getInstanceMethod(target, newSelector); | ||
[ASHook swizzle:target selector:originalSelector newSelector:newSelector originalMethod:originalMethod newMethod:newMethod]; | ||
} | ||
} | ||
|
||
+ (void)runBlock:(void (^)(__unsafe_unretained id _self))block onTarget:(id)targetClass beforeClassSelector:(SEL)originalSelector { | ||
id target = object_getClass(targetClass); | ||
Method originalMethod = class_getClassMethod(target, originalSelector); | ||
SEL newSelector = [self insertBlock:block onTarget:target originalSelector:originalSelector originalMethod:originalMethod]; | ||
if (newSelector) { | ||
Method newMethod = class_getClassMethod(target, newSelector); | ||
[ASHook swizzle:target selector:originalSelector newSelector:newSelector originalMethod:originalMethod newMethod:newMethod]; | ||
} | ||
} | ||
|
||
#pragma mark - Private methods | ||
|
||
/*! @brief Creating and adding a new implementation for the original method with the block included. */ | ||
+ (SEL)insertBlock:(void (^)(__unsafe_unretained id _self))block | ||
onTarget:(id)target | ||
originalSelector:(SEL)originalSelector | ||
originalMethod:(Method)originalMethod { | ||
NSString *swizzledMethodSuffix = @"_ASMethodSwizzled"; | ||
NSString *swizzledMethodName = [NSString stringWithFormat:@"%@%@", NSStringFromSelector(originalSelector), swizzledMethodSuffix]; | ||
SEL newSelector = NSSelectorFromString(swizzledMethodName); | ||
id actionBlock = ^(__unsafe_unretained id _self) { | ||
if (block != nil) { | ||
block(_self); | ||
} | ||
((void ( *)(id, SEL))objc_msgSend)(_self, newSelector); // Using ObjC messaging directly to avoid ARC messing with the lifecycle of the original object. (ie. had issues with some classes' dealloc otherwise) | ||
}; | ||
IMP impl = imp_implementationWithBlock(actionBlock); | ||
const char *encoding = method_getTypeEncoding(originalMethod); | ||
if (!class_addMethod(target, newSelector, impl, encoding)) { | ||
NSLog(@"Failed to add method: %@ on %@", NSStringFromSelector(newSelector), target); | ||
return nil; | ||
} | ||
return newSelector; | ||
} | ||
|
||
@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
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
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