情形:我们需要hook tableview的代理对象
(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath 方法,在执行该方法的时候做一下操作,
但是,如果tableview的代理对象并没有实现该方法,我们该怎么办呢? 方案就是,我们在工具类中判断一下,如果代理对象没有实现该方法
我们就给代理对象添加一个实现,这样我们就可以hook 这个方法,然后在适当时机做我们想要实现的操作,这里,我们可以将我们自己做的一个方法实现
类比做“引子”,他就是起到了一个“引子”的作用,并没有具体的实现,但是没有他又不行 ,这里工具类中的 + (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath方法就是“引子”
+ (void)hookWillDisplayCellWithPresenter:(NSObject *)presenter
{
[presenter aspect_hookSelector:@selector(tableView:willDisplayCell:forRowAtIndexPath:) withOptions:AspectPositionAfter usingBlock:^(id<AspectInfo> data) {
if (data.arguments.count < 2) {
return;
}
UITableView *tableView = data.arguments.firstObject;
UITableViewCell *cell = data.arguments[1];
if (![tableView isKindOfClass:[UITableView class]] ||
![cell isKindOfClass:[UITableViewCell class]]) {
return;
}
[tableView bringSubviewToFront:cell];
} error:nil];
}
上面是hook方法的实现,下面是判断有没有实现,如果没有实现,将自己的一个方法添加到该对象上,作为引子
+ (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(@"执行执行之星");
}
NSObject *presenter = scrollView.delegate;
if ([presenter respondsToSelector:@selector(tableView:willDisplayCell:forRowAtIndexPath:)]) {
[self hookWillDisplayCellWithPresenter:presenter];
} else {
IMP tmpImp = [self methodForSelector:@selector(tableView:willDisplayCell:forRowAtIndexPath:)];
BOOL result = class_addMethod([presenter class], @selector(tableView:willDisplayCell:forRowAtIndexPath:),tmpImp, [@"v@:@@@" UTF8String]);
if (result) {
[self hookWillDisplayCellWithPresenter:presenter];
}
}
}
注意,这三段代码都是在同一个类中实现的,最下面的一段代码也是在一个类方法中,这里是在一个类方法中hook presenter的 一个可能没有实现的方法,如果没有实现,
该类就帮他实现,从而在适当的时机触发present的被hook的方法,达到我们捕捉时机的目的