我想为 objective-c 中的对象构建一个小型插件系统。
现在我想动态地(在运行时)向对象中的每个可用函数添加一行代码。
我试过运行时库,但还没有找到解决方案。
到目前为止我尝试过的是:
id (^impyBlock)(id, id, ... ) = ^(id self_, id arguments, ...)
{
// My custom code for every function here
id (*func)(__strong id,SEL,...) = (id (*)(__strong id, SEL, ...))imp;
return func(obj, s, arguments);
};
id (*impyFunct)(id, SEL,...) = imp_implementationWithBlock(impyBlock);
method_setImplementation(mList[i], impyFunct);
我的问题是,当有多个参数时,我没有机会将它们传递给“func()”。据我所知,这在 C 中是不可能的。
我想到的另一个解决方案是使用方法调配来施展魔法。
步骤:
- 创建一个“swizzle 方法”,它只调用我的自定义代码,然后调用原始方法(通过命名模式)
- 使用“swizzle 方法”之一更改每个函数的 IMP
- 使用“旧”实现创建一个新方法并将名称更改为类似于“___name”的模式
在这个解决方案中,我卡在了第 3 点。我还没有设法动态创建一个完整的新方法。
有没有人可以帮助我解决上述问题,或者有其他解决方案来实现“捕获所有方法功能”。
最好的是像 forwardInvocation 这样的东西,它也可以捕获已经定义的函数。
感谢您的帮助!
最佳答案
让我把它分成两部分,因为我无法理解你的两个问题之间的联系。
我。使用“旧”实现创建一个新方法并将名称更改为类似“___name”的模式
这很简单,尽管我不明白这将如何解决您的问题。您仍然不能将可变参数函数参数传递给这样的方法(您是对的,这不能在 C 中完成)。
IMP swapImpForSelector(Class cls, SEL sel, IMP newImp)
{
Method m = class_getInstanceMethod(cls, sel);
IMP oldImp = method_setImplementation(m, newImp);
NSString *newSel = [NSString stringWithFormat:@"__prefixed_%@", NSStringFromSelector(sel)];
const char *type = method_getTypeEncoding(m);
class_addMethod(cls, NSSelectorFromString(newSel), oldImp, type);
return oldImp;
}
二。如果你想在函数之间传递可变参数,你可能需要退回到大量的汇编黑客攻击。幸运的是,一些聪明人已经为您做到了。
要么使用 NSInvocation class ,或者如果还不够,则 libffi甚至更低。
关于ios - Objective-C 为对象的每个方法添加功能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17116855/