iOS 使用 IMP 调用 class 方法

iOS invoke class method with IMP

假设我正在开发一个调整应用程序,我想创建一个 Class 的实例,其 header 无法导入,但我知道 class 名称,class 方法和实例方法 如何在带参数的 class 方法中创建它? 说这个 Class 使用 class 方法调用 MMClass

  +(instancetype)do:(NSString*)string for:(NSString *)antherString; 

我的操作如下:

Class class = objc_getClass("MMClass");
Method initMethod = class_getClassMethod(class,
                                             @selector(do:for:));
IMP imp = method_getImplementation(initMethod);
id instance = imp(class,@selector(do:for:),@"do",@"ye");

这样对吗?

首先,我不确定我说的是否很明显,但为什么不创建您自己的 header 包含您要使用的声明并导入它(或者只是在如果您只打算在一个文件中使用它,请放在文件顶部)?并正常调用方法?而不是经历所有这些混乱?所有编译器关心的是它看到一些你想调用的方法的声明。

当您使用函数指针调用实际方法实现时,您需要将其转换为与方法签名对应的正确类型的函数指针:

Class class = objc_getClass("MMClass");
Method initMethod = class_getClassMethod(class, @selector(do:for:));
IMP imp = method_getImplementation(initMethod);
id (*foo)(Class, SEL, NSString *, NSString *) =
    (id (*)(Class, SEL, NSString *, NSString *))imp;
id instance = foo(class, @selector(do:for:), @"do", @"ye");

但是得到一个你只打算使用一次的 IMP 是愚蠢的。相反,您应该将 objc_msgSend 转换为所需的函数指针类型,然后直接调用它:

Class class = objc_getClass("MMClass");
id (*foo)(Class, SEL, NSString *, NSString *) =
    (id (*)(Class, SEL, NSString *, NSString *))objc_msgSend;
id instance = foo(class, @selector(do:for:), @"do", @"ye");