Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add block based swizzle api #18

Merged
merged 1 commit into from
Nov 28, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions JRSwizzle.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,39 @@
+ (BOOL)jr_swizzleMethod:(SEL)origSel_ withMethod:(SEL)altSel_ error:(NSError**)error_;
+ (BOOL)jr_swizzleClassMethod:(SEL)origSel_ withClassMethod:(SEL)altSel_ error:(NSError**)error_;


/**
```
__block NSInvocation *invocation = nil;
invocation = [self jr_swizzleMethod:@selector(initWithCoder:) withBlock:^(id obj, NSCoder *coder) {
NSLog(@"before %@, coder %@", obj, coder);

[invocation setArgument:&coder atIndex:2];
[invocation invokeWithTarget:obj];

id ret = nil;
[invocation getReturnValue:&ret];

NSLog(@"after %@, coder %@", obj, coder);

return ret;
} error:nil];
```
*/
+ (NSInvocation*)jr_swizzleMethod:(SEL)origSel withBlock:(id)block error:(NSError**)error;

/**
```
__block NSInvocation *classInvocation = nil;
classInvocation = [self jr_swizzleClassMethod:@selector(test) withBlock:^() {
NSLog(@"before");

[classInvocation invoke];

NSLog(@"after");
} error:nil];
```
*/
+ (NSInvocation*)jr_swizzleClassMethod:(SEL)origSel withBlock:(id)block error:(NSError**)error;

@end
24 changes: 24 additions & 0 deletions JRSwizzle.m
Original file line number Diff line number Diff line change
Expand Up @@ -139,4 +139,28 @@ + (BOOL)jr_swizzleClassMethod:(SEL)origSel_ withClassMethod:(SEL)altSel_ error:(
return [GetClass((id)self) jr_swizzleMethod:origSel_ withMethod:altSel_ error:error_];
}

+ (NSInvocation*)jr_swizzleMethod:(SEL)origSel withBlock:(id)block error:(NSError**)error {
IMP blockIMP = imp_implementationWithBlock(block);
NSString *blockSelectorString = [NSString stringWithFormat:@"_jr_block_%@_%p", NSStringFromSelector(origSel), block];
SEL blockSel = sel_registerName([blockSelectorString cStringUsingEncoding:NSUTF8StringEncoding]);
Method origSelMethod = class_getInstanceMethod(self, origSel);
const char* origSelMethodArgs = method_getTypeEncoding(origSelMethod);
class_addMethod(self, blockSel, blockIMP, origSelMethodArgs);

NSMethodSignature *origSig = [NSMethodSignature signatureWithObjCTypes:origSelMethodArgs];
NSInvocation *origInvocation = [NSInvocation invocationWithMethodSignature:origSig];
origInvocation.selector = blockSel;

[self jr_swizzleMethod:origSel withMethod:blockSel error:nil];

return origInvocation;
}

+ (NSInvocation*)jr_swizzleClassMethod:(SEL)origSel withBlock:(id)block error:(NSError**)error {
NSInvocation *invocation = [GetClass((id)self) jr_swizzleMethod:origSel withBlock:block error:error];
invocation.target = self;

return invocation;
}

@end