SilverFruity / OCRunner

Execute Objective-C code as script. AST Interpreter. iOS hotfix SDK.
MIT License
660 stars 149 forks source link

runtime方式调用类方法时,无法传参的问题。 #25

Closed zqgogo closed 2 years ago

zqgogo commented 2 years ago

OCRunner version: 1.2.6

description: 当使用runtim动态调用类方法的时候,被调用的类方法可以被ocrunner替换,也能调到原来的方法,但是参数一直为nil,没能传递过来。

example: 使用method_getImplementation这个方式获取到imp指针,利用runtime方式调用类方法。

目前我只能排查到ORCoreImp.m文件内,methodIMP方法里,第23到27行这儿,sel和target都可以正常获取到,但是第25行获取方法签名就为nil了,所以后面的循环也直接没有跑,导致参数没有被添加到argValues数组中,后续就无法获取到参数了。 经测试,正常调用是可以获取到的,只有runtime这种方式调用的时候,获取不到参数。

麻烦大佬看一下。

SilverFruity commented 2 years ago

能否给一份最简单的复现代码呢

zqgogo commented 2 years ago

能否给一份最简单的复现代码呢

调用部分的代码如下,在AppDelegate中: NSString *methodName = @"testFunc:"; SEL methodSelector = NSSelectorFromString(methodName); Class cla = NSClassFromString(@"ViewController"); Method method = class_getClassMethod(cla, methodSelector); IMP imp = method_getImplementation(method); void (*func)(id, SEL, id) = (void (*)(id, SEL, id))imp; func(self, methodSelector, @"testParam");

image

ViewController中增加了一个类方法用于测试: + (void)testFunc:(NSString *)strParam { NSLog(@"-----%@", strParam); } 热更新补丁中修改如下: + (void)testFunc:(NSString *)strParam { [ViewController ORGtestFunc:strParam]; }

然后没有热更新补丁的时候,可以正常输出字符串“testParam”,添加了热更新补丁后,报错信息为“Can't find object or class: strParam”

zqgogo commented 2 years ago

能否给一份最简单的复现代码呢

调用部分的代码如下,在AppDelegate中: NSString *methodName = @"testFunc:"; SEL methodSelector = NSSelectorFromString(methodName); Class cla = NSClassFromString(@"ViewController"); Method method = class_getClassMethod(cla, methodSelector); IMP imp = method_getImplementation(method); void (*func)(id, SEL, id) = (void (*)(id, SEL, id))imp; func(self, methodSelector, @"testParam"); image ViewController中增加了一个类方法用于测试: + (void)testFunc:(NSString *)strParam { NSLog(@"-----%@", strParam); } 热更新补丁中修改如下: + (void)testFunc:(NSString *)strParam { [ViewController ORGtestFunc:strParam]; }

然后没有热更新补丁的时候,可以正常输出字符串“testParam”,添加了热更新补丁后,报错信息为“Can't find object or class: strParam”

抱歉,是我自己的问题,刚调了半天,搞定了。 是调用的时候出错了,最后调用的时候,func(self, methodSelector, @"testParam");,这儿的第一个参数不应该是self,而应该是cla,对应的那个类,修改了之后,就可以正常输出了。因为之前的代码一直是这样调用的,所以没注意到。大佬你这边应该是没问题的。