有什么办法可以在iOS应用程序中列出所有的方法吗?
我基本上正在寻找一种方法来检测何时/什么第三方库swizzle。 我最近遇到了一个广告库使用了AFNetworking的古怪分支的情况。 AFNetworking调整NSURLSessionTask,并且在某些情况下两个swizzles不能很好地播放。 我真的希望能够检测和理智检查这种事情,理想情况下,甚至保持在应用程序中的每个debugging方法的版本化的转储,所以我们有一些可见的谁是猴子修补什么和风险是什么。 谷歌和堆栈溢出search已经没有什么了,但只有一堆教程如何swizzle。 有人遇到这个问题或有解决办法? 它看起来像我可以使用objc / runtime.h编码的东西,但我无法想象我是第一个需要这个人。
这是我能得到的最接近,几个小时的修补。 它涉及到使用mach_override的叉子,关于加载顺序的几个DYLD怪癖,以及疯狂的黑客的胃。
它只能在模拟器上工作,但是对于你似乎已经使用的用例来说就足够了(我当然希望你没有设备依赖关系)。
代码的肉看起来像这样:
#include <objc/runtime.h> #include <mach_override/mach_override.h> // It is extremely important that we have DYLD run this constructor as soon as the binary loads. If we were to hook // this at any other point (for example, another category on NSObject, in the main application), what could potentially // happen is other `+load` implementations get invoked before we have a chance to hook `method_exchangeImplementation`, // and we don't get to see those swizzles. // It is also extremely important that this exists inside its own dylib, which will be loaded by DYLD before _main() is // initialized. You must also make sure that this gets loaded BEFORE any other userland dylibs, which can be enforced by // looking at the order of the 'link binary with libraries' phase. __attribute__((constructor)) static void _hook_objc_runtime() { kern_return_t err; MACH_OVERRIDE(void, method_exchangeImplementations, (Method m1, Method m2), &err) { printf("Exchanging implementations for method %s and %s.\n", sel_getName(method_getName(m1)), sel_getName(method_getName(m2))); method_exchangeImplementations_reenter(m1, m2); } END_MACH_OVERRIDE(method_exchangeImplementations); MACH_OVERRIDE(void, method_setImplementation, (Method method, IMP imp), &err) { printf("Setting new implementation for method %s.\n", sel_getName(method_getName(method))); method_setImplementation_reenter(method, imp); } END_MACH_OVERRIDE(method_setImplementation); }
这是令人惊讶的简单,并产生这样的输出:
交换方法描述和custom_description的实现。
没有什么好的办法(没有使用断点并查看堆栈跟踪)来弄清哪个类正在被debugging,但是对于大多数情况,只要看看select器应该给你一个从哪里去的提示。
它似乎与我在+load
创build的几个类别一起工作,从我读取mach_override
和DYLD的内部,只要你的库加载顺序设置正确,你可以期望这之前被初始化任何其他用户的土地代码,如果你把它放在它自己的dynamic库。
现在,我不能保证这一点的安全性,但作为一个debugging工具,似乎有用,所以我已经发布我的例子github:
https://github.com/richardjrossiii/mach_override_example
这是麻省理工学院许可的,所以随意使用,因为你认为合适的。