我想在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()”。 AFAIK这在C中是不可能的。
我想到的另一个解决方案是通过方法调配来做一些魔术。
分步骤:
在这个解决方案中,我陷入了第3点。我还没有设法动态创建一个完整的新方法。
是否有人可以帮我解决上述问题,或者有其他方法可以解决“捕捉所有方法功能”。
最好的东西就像forwardInvocation,它也捕获已定义的函数。
感谢您的帮助!
答案 0 :(得分:4)
Lemme将其分为两部分,因为我无法理解你的两个问题。
予。使用“旧”实现创建一个新方法,并将名称更改为类似“___ 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;
}
II。如果你想在函数之间传递可变参数,你可能需要回到沉重的程序集hackage。幸运的是,一些聪明人已经为你做过这件事。
使用NSInvocation class,或者如果不够,则libffi甚至更低。
答案 1 :(得分:2)
为任意对象执行此操作将非常困难。看一下AspectCocoa这些内容,但你会发现它不能很好地工作,不建议在生产环境中使用。
但是对于一个插件系统,你最好只定义类似PluggableObject类的东西,它设计时考虑了扩展。忘记在任意方法中运行任意块 - 而是定义可以插入内容的特定“套接字”以及这些东西可以遵循的接口以获得您想要支持的功能。它会更加稳定,更容易添加和修复。