利用Objective-C运行时hook函数的三种方法
方法一,hook已有公开头文件的类:
首先写一个Utility函数:
@implementation UIWebBrowserViewHookstatic IMP webView_didFinishLoadForFrame = NULL;+ (void)hook{ Class hookedClass = objc_getClass("UIWebBrowserView"); SEL sel = @selector(webView:didFinishLoadForFrame:); replaceImplementation([self class], hookedClass, sel, webView_didFinishLoadForFrame);}- (void)webView:(id)arg1 didFinishLoadForFrame:(id)arg2{ // 需要这样来调用被替换掉的原实现 webView_didFinishLoadForFrame(self, @selector(webView:didFinishLoadForFrame:), arg1, arg2); NSLog(@"webView:didFinishLoadForFrame:");}@end在程序启动的时候调用一下 [UIWebBrowserViewHook hook] 即可。使用一个UIWebView打开一个网页,即会打印NSLog。
三种方法的比较:
最方便的当然是第一种,但需要是hook有公开头文件的类。
方法二和方法三都新建了一个类,方法二需要描述selector的types,这个比较麻烦,如例子中的"v@:@@"表示返回值为void,第一和第二个参数都是id。方法三不用types,但要增加全局变量。
Objective-C的runtime参考资料:
http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Introduction/Introduction.html#//apple_ref/doc/uid/TP40008048