SDMagicHook
一种适用于 Objective-C 和 Swift 的安全且影响受限的方法钩子。
改进
使用 method_exchangeImplementations 进行的传统方法交换非常简单,但它有许多限制和缺陷。
- 每当您想交换一个方法时,都必须在类类别中添加一个新的方法。
- 不同类别中使用相同选择器的不同方法实现将导致方法冲突。
- 方法交换将影响目标类的所有实例,然而在大多数情况下,这并不必要而且可能有副作用。
现在 SDMagicHook 将解决上述问题。
变更日志
2020.05.01 -- 发布兼容 KVO 的版本 "1.2.4"
2020.03.09 -- 兼容 KVO
用法
示例:挂钩CALayer的setBackgroundColor:
方法以找出暗中更改视图背景色的人
[self.view.layer hookMethod:@selector(setBackgroundColor:) impBlock:^(CALayer *layer, CGColorRef color){
[layer callOriginalMethodInBlock:^{
[layer setBackgroundColor:color];
}];
NSLog(@"%@", [NSString stringWithFormat:@"AHA! Catch it! Here are the clues.\n\n%@", [NSThread callStackSymbols]]);
}];
示例:挂钩UIButton的pointInside:withEvent:
方法以扩大热区域
- (void)expand:(Boolean)yn {
if (yn) {
__weak typeof(self) weakSelf = self;
_hookID = [_button hookMethod:@selector(pointInside:withEvent:) impBlock:^(UIView *v, CGPoint p, UIEvent *e){
__block BOOL res = false;
[v callOriginalMethodInBlock:^{
res = [v pointInside:p withEvent:e];
}];
if (res) return YES;
return [weakSelf pointCheck:p view:v];
}];
} else {
[_button removeHook:@selector(pointInside:withEvent:) strId:_hookID];
}
}
示例:挂钩类方法
- (void)hookClassMethod {
[[DemoVC3 class] hookMethod:@selector(testClassMethod) key:&testClassMethodTag impBlock:^(id cls){
[cls callOriginalMethodInBlock:^{
[[DemoVC3 class] testClassMethod];
}];
printf(">> hooked testClassMethod");
}];
}
+ (void)testClassMethod {
printf(">> %s", sel_getName(_cmd));
}
- (void)dealloc {
[[DemoVC3 class] removeHook:@selector(testClassMethod) key:&testClassMethodTag];
}
示例:观察任意实例的dealloc事件。
[[NSObject new] addObjectDeallocCallbackBlock:^{
printf("Will dealloc...");
}];
示例:使用Swift挂钩UIViewController的viewDidDisappear:
方法
override func viewDidLoad() {
super.viewDidLoad()
let imp: @convention(block) (UIViewController, Bool) -> Void = { (vc, flag) in
vc.callOriginalMethod {
vc.viewDidDisappear(flag)
}
print(vc)
}
rootVC = navigationController?.children.first
hookID = rootVC?.hookMethod(#selector(UIViewController.viewDidDisappear(_:)), impBlock: imp)
}
许可证
MIT许可证。