diff --git a/Example/Stinger/ASViewController.m b/Example/Stinger/ASViewController.m index afe1e3b..560e95a 100644 --- a/Example/Stinger/ASViewController.m +++ b/Example/Stinger/ASViewController.m @@ -26,6 +26,11 @@ - (void)setFrame:(CGRect)rect { } +- (BOOL)setFrame:(CGRect)rect object:(NSString *)obj num:(NSInteger)num { + NSLog(@"origin fun: %@, %@, %ld", @(rect), obj, num); + return YES; +} + - (void)viewDidLoad { [super viewDidLoad]; [self.class st_hookInstanceMethod:@selector(methodA) option:STOptionBefore usingIdentifier:@"hook methodA before" withBlock:^(id params) { @@ -34,7 +39,18 @@ - (void)viewDidLoad { [self.class st_hookInstanceMethod:@selector(methodA) option:STOptionAfter usingIdentifier:@"hook methodA after" withBlock:^(id params) { }]; - + + [self.class st_hookInstanceMethod:@selector(setFrame:object:num:) option:STOptionAfter usingIdentifier:@"change arg" withBlock:^BOOL(id params, CGRect rect, NSString *obj, NSInteger num) { + [params setArgument:@(CGRectMake(5, 6, 7, 8)) atIndex:0]; + [params setArgument:@"hook success" atIndex:1]; + [params setArgument:@(num + 1) atIndex:2]; + BOOL returnValue; + [params invokeAndGetOriginalRetValue:&returnValue]; + return returnValue; + }]; + [self setFrame:CGRectMake(1, 2, 3, 4) object:@"not hook" num:111]; + + // [self.class aspect_hookSelector:@selector(methodA) withOptions:AspectPositionBefore usingBlock:^(id params) { // // } error:nil]; diff --git a/Stinger/Classes/STDefines.h b/Stinger/Classes/STDefines.h index c4ab8bd..11d79b3 100644 --- a/Stinger/Classes/STDefines.h +++ b/Stinger/Classes/STDefines.h @@ -53,6 +53,7 @@ typedef NS_ENUM(NSInteger, STHookResult) { - (SEL)sel; - (NSArray *)arguments; - (NSString *)typeEncoding; +- (void)setArgument:(id)arg atIndex:(NSInteger)idx; - (void)invokeAndGetOriginalRetValue:(void *)retLoc; @end diff --git a/Stinger/Classes/StingerParams.m b/Stinger/Classes/StingerParams.m index d3272c4..75f5522 100644 --- a/Stinger/Classes/StingerParams.m +++ b/Stinger/Classes/StingerParams.m @@ -19,7 +19,7 @@ @interface StingerParams () @property (nonatomic) IMP originalIMP; @property (nonatomic) void **args; @property (nonatomic) NSArray *argumentTypes; -@property (nonatomic) NSArray *arguments; +@property (nonatomic) NSMutableArray *arguments; @end @implementation StingerParams @@ -46,13 +46,37 @@ - (SEL)sel { } - (NSArray *)arguments { - return _arguments; + return [_arguments copy]; } - (NSString *)typeEncoding { return _types; } +/// 修改函数参数 +/// - Parameters: +/// - arg: 对应的参数,值类型请转换为NSValue传递 +/// - idx: 序号,默认从0开始 +- (void)setArgument:(id)arg atIndex:(NSInteger)idx { + _arguments[idx]= arg; + NSString *argTypeStr = _argumentTypes[idx + 2]; + const char *argType = argTypeStr.UTF8String; + if (strcmp(argType, @encode(id)) == 0 || strcmp(argType, @encode(Class)) == 0) { + void **objPointer = _args[idx + 2]; + *objPointer = (__bridge void *)(arg); + return; + } + if ([arg isKindOfClass:NSValue.class]) { + if (@available(iOS 11.0, *)) { + NSUInteger valueSize = 0; + NSGetSizeAndAlignment(argType, &valueSize, NULL); + [(NSValue *)arg getValue:_args[idx + 2] size:valueSize]; + } else { + [(NSValue *)arg getValue:_args[idx + 2]]; + } + } +} + - (void)invokeAndGetOriginalRetValue:(void *)retLoc { NSMethodSignature *signature = [NSMethodSignature signatureWithObjCTypes:_types.UTF8String]; NSInteger count = signature.numberOfArguments; @@ -69,12 +93,11 @@ - (void)invokeAndGetOriginalRetValue:(void *)retLoc { #pragma - mark Private - (void)st_genarateArguments { - NSMutableArray *args = [[NSMutableArray alloc] initWithCapacity:_argumentTypes.count]; + _arguments = [NSMutableArray array]; for (NSUInteger i = 2; i < _argumentTypes.count; i++) { id argument = [self st_argumentWithType:_argumentTypes[i] index:i]; - [args addObject:argument ?: NSNull.null]; + [_arguments addObject:argument ?: NSNull.null]; } - _arguments = [args copy]; } - (id)st_argumentWithType:(NSString *)type index:(NSUInteger)index {