需要特殊说明的是:
- 1、hook类方法需要用元类
object_getClass([Person class])
调用+ (id<AspectToken>)aspect_hookSelector:(SEL)selector withOptions:(AspectOptions)options usingBlock:(id)block error:(NSError **)error;
方法;- 2、如果要全局hook某个成员方法,则需要用类名调用
- (id<AspectToken>)aspect_hookSelector:(SEL)selector withOptions:(AspectOptions)options usingBlock:(id)block error:(NSError **)error;
方法;- 3、如果只是hook某个实例的某个成员方法,则需要用该类的实例去调用。
使用示例:
//Person.h
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface Person : NSObject
+ (void)printHello;
- (void)instanceMethod;
@end
NS_ASSUME_NONNULL_END
//Person.m
#import "Person.h"
@implementation Person
+ (void)printHello {
NSLog(@"printHello");
}
- (void)instanceMethod {
NSLog(@"instanceMethod");
}
@end
//实现
- (void)aspects {
//1. 用元类去hook类方法
[object_getClass(Person.class) aspect_hookSelector:@selector(classMethodOfPrintHello) withOptions:AspectPositionBefore usingBlock: ^{
NSLog(@"classMethodOfPrintHello前");
} error:nil];
//在调用这个方法打印之前, 会先打印上面的
[Person classMethodOfPrintHello];
//2. 用类名去全局替换
[UIViewController aspect_hookSelector:@selector(viewDidLoad) withOptions:AspectPositionBefore usingBlock:^(id<AspectInfo> obj){
NSLog(@"viewDidLoad前--%@", obj);
} error:nil];
//3. 用实例对象,只对该对象的指定成员方法起作用
Person *per = [[Person alloc] init];
[per aspect_hookSelector:@selector(instanceMethodOfPrintOK) withOptions:AspectPositionBefore usingBlock: ^{
NSLog(@"instanceMethodOfPrintOK前");
} error:nil];
[per instanceMethodOfPrintOK];
//验证3: per2在打印之前,并没有打印`instanceMethodOfPrintOK前`
NSLog(@"======================");
Person *per2 = [[Person alloc] init];
[per2 instanceMethodOfPrintOK];
}
打印输出
classMethodOfPrintHello前
classMethodOfPrintHello
instanceMethodOfPrintOK前
instanceMethodOfPrintOK
======================
instanceMethodOfPrintOK
viewDidLoad前--<AspectInfo: 0x6000028c59c0>//UINavigationController
viewDidLoad前--<AspectInfo: 0x6000028fe7a0>//ViewController
viewDidLoad前--<AspectInfo: 0x6000028ffba0>//UIInputWindowController
网友评论