码迷,mamicode.com
首页 > 其他好文 > 详细

hook的使用

时间:2015-10-14 12:51:06      阅读:161      评论:0      收藏:0      [点我收藏+]

标签:

OC runtime 提供了动态替换Method 实现的能力,加上category的使用,可以实现一种叫 swizzle的技术,从而给问题定位提供了一种方法。

举个例子,NSNotificationCenter 注册的observer 是通过assign 方法保留observer引用(而不是weak 或 retain、strong),这样的话如果某个observer只是注册而没有注销,那么这个observer释放后,NSNotificationCenter 发送通知时将找不到这个observer,因为这个observer已经成了野指针,从而发生crash。

那么到底是那个observer 只注册而没有注销呢? 可以通过给 NSNotificationCenter 增加一个category ,在category中通过swizzle 给原来的注册与注销方法添加log 来查看。


category的头文件:

增加了swizzle 类方法,在app 启动时调用

/*
* NSNotificationCenter+TestHook.h
*/

#import <Foundation/Foundation.h>

@interface NSNotificationCenter (TestHook)

+ (void) swizzle;
@end

实现,增加两个hook 方法,分别给注册和注销方法添加log:

注意hook方法不能在头文件暴露以防被直接调用,因为在使用method_exchangeImplimentaions之前,直接调用会发生递归。

#import "NSNotificationCenter+TestHook.h"
#import <objc/runtime.h>


@implementation NSNotificationCenter (TestHook)

-(void)hook_addObserver:(id)observer selector:(SEL)aSelector name:(NSString *)aName object:(id)anObject{
    NSLog(@"====== add observer for:%@, selector: %s, class %s", aName, sel_getName(aSelector), class_getName([observer class]));
    [self hook_addObserver:observer selector:aSelector name:aName object:anObject];
}

- (void)hook_removeObserver:(id)observer name:(nullable NSString *)aName object:(nullable id)anObject{
        NSLog(@"====== remove observer for:%@,  class %s", aName, class_getName([observer class]));
    [self hook_removeObserver:observer name:aName object:anObject];
    
}

+(void)swizzle{
    Method ori_Method =  class_getInstanceMethod([NSNotificationCenter class], @selector(addObserver:selector:name:object:));
    Method my_Method = class_getInstanceMethod([NSNotificationCenter class], @selector(hook_addObserver:selector:name:object:));
    
    method_exchangeImplementations(ori_Method, my_Method);
    
    Method ori_remove = class_getInstanceMethod([NSNotificationCenter class], @selector(removeObserver:name:object:));
    Method my_remove = class_getInstanceMethod([NSNotificationCenter class], @selector(hook_removeObserver:name:object:));
    method_exchangeImplementations(ori_remove, my_remove);
    
}

@end

然后在应用AppDelegeate中调用 :

....
#import "NSNotificationCenter+TestHook.h"
...

@implementation MyAppDelegate

...

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

...

 [NSNotificationCenter swizzle];

...

}

...

@end


这样就能清楚的看到哪些observer注册了哪些通知,以及在什么时候注销了通知。

hook的使用

标签:

原文地址:http://my.oschina.net/u/255456/blog/516912

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!