objective-c - 是否可以为 Objective-C 中的每个方法调用生成一个包装器?
问题描述
我有一个包含很多课程的项目。我想在运行时记录(例如到 stderr)每个选择器的调用。
我的主要要求是不要更改现有代码,因此我不能只在每次调用开始时记录函数的参数。
如果在程序执行期间调用了某个方法,例如
@implementation Class1
// ...
- (int)someFunc:(Class2*) a andClass3:(Class3*)b
{
}
// ...
@end
我想用类似的东西替换它:
- (int)someFuncWrapper:(Class2*) a andClass3:(Class3*)b
{
NSLog(@"- (int)someFuncWrapper:a andClass3:b <= a=%@, ab=%@", a, b);
return [someFunc: a andClass3:b];
}
可能吗?
我读过方法调配、KVO、转发消息。
我目前的方法调配方法会导致无限递归:
- (int)funcToSwizzle:(int)a andB:(int)b
{
int r = a+b;
NSLog(@"funcToSwizzle: %d", r);
return r;
}
- (void)doSimpleSwizzling
{
NSLog(@"r1 = %d", [self funcToSwizzle:10 andB:20]);
Class curClass = NSClassFromString(@"HPTracer");
unsigned int methodCount = 0;
Method *methods = class_copyMethodList( curClass, &methodCount);
for (int i=0; i<methodCount; ++i)
{
SEL originalSelector = method_getName(methods[i]);
if ( strcmp("funcToSwizzle:andB:", sel_getName(originalSelector)) == 0 )
{
Method m1 = class_getInstanceMethod(curClass, originalSelector);
id block3 = ^(id self, int a, int b) {
NSLog(@"My block: %d", a*b);
// get current implementation of "funcToSwizzle".
// copy it. store that "IMP"/"void *" etc
return [self funcToSwizzle:a andB:b];
};
IMP imp3 = imp_implementationWithBlock(block3);
method_setImplementation(m1, imp3);
}
}
NSLog(@"r2 = %d", [self funcToSwizzle:10 andB:20]);
}
而且恐怕不可能block3
在运行时生成一个或某些方法。有NSSelectorFromString
,但没有ImplementationFromString
。
UPD
我查看了 DTrace util,它看起来非常强大,但不符合我的需求。它需要在 Mac OS 上禁用 SIP,并且在 iOS 上是不可能的,或者在越狱设备上是可能的。
我需要的方法拦截是为调试和生产构建模式创建一个稳定的自定义“框架”。
解决方案
推荐阅读
- python-2.7 - Urllib2 通过代理和信任不受信任的 SSL 证书
- hyperledger-fabric - 在 Hyperledger Fabric 中,如何在部署时保持链代码(源代码)私有?
- sql-server - 如何根据条件从组内获取数据
- r - 如何在 mapdeck 中使用 set_token?
- c# - 模型值未从主视图进入局部视图 - C# MVC
- node.js - 在 NodeJS 中使用 which 命令
- azure - 为什么托管实例需要更多时间来创建?
- python - 在中心显示轴,但在左侧保留标签
- python - FailedPreconditionError: Error while reading resource variable module..在评估张量流预训练模型时
- ubuntu - /lib64/libm.so.6:版本 / 和 /lib64/libstdc++.so.6:未找到版本