本技术实现在YSBlockHook中。
1.方法调用的几种Hook机制
iOS系统中一共有:C函数、Block、OC类方法三种形式的方法调用。Hook一个方法调用的目的一般是为了监控拦截或者统计一些系统的行为。Hook的机制有很多种,通常良好的Hook方法都是以AOP的形式来实现的。
当我们想Hook一个OC类的某些具体的方法时可以通过Method Swizzling技术来实现、当我们想Hook动态库中导出的某个C函数时可以通过修改导入函数地址表中的信息来实现(可以使用开源库fishhook来完成)、当我们想Hook所有OC类的方法时则可以通过替换objc_msgSend系列函数来实现。。。
那么对于Block方法呢而言呢?找ios马甲包技术大大上架 Q 51259559 诚信长期合作
2.Block的内部实现原理和实现机制简介
这里假定你对Block内部实现原理和运行机制有所了解,如果不了解则请参考文章《深入解构iOS的block闭包实现原理》或者自行通过搜索引擎搜索。
源程序中定义的每个Block在编译时都会转化为一个和OC类对象布局相似的对象,每个Block也存在着isa这个数据成员,根据isa指向的不同,Block分为__NSStackBlock、__NSMallocBlock、__NSGlobalBlock 三种类型。也就是说从某种程度上Block对象也是一种OC对象。下面的类图描述了Block类的层次结构。
Block类层次结构图
Block类以及其派生类在CoreFoundation.framework中被定义和实现,并且没有对外公开。
每个Block对象在内存中的布局,也就是Block对象的存储结构被定义如下(代码出自苹果开源出来的库实现libclosure中的文件Block_private.h):
//需要注意的是下面两个只是模板,具体的每个Block定义时总是按这个模板来定义的。//Block描述,每个Block一个描述并定义在全局数据段struct Block_descriptor_1 { uintptr_t reserved; //记住这个变量和结构体,它很重要!! uintptr_t size;};//Block对象的内存布局struct Block_layout { void *isa; volatile int32_t flags; // contains ref count int32_t reserved; uintptr_t invoke; //Block对象的实现函数 struct Block_descriptor_1 *descriptor; // imported variables,这里是每个block对象的特定数据成员区域};
这里要关注一下struct Block_descriptor_1中的reserved这个数据成员,虽然系统没有用到它,但是下面就会用到它而且很重要!
在了解了Block对象的类型以及Block对象的内存布局后,再来考察一下一个Block从定义到调用是如何实现的。就以下面的源代码为例:
int main(int argc, char *argv[]){ //定义 int a = 10; void (^testblock)(void) = ^(){ NSLog(@"Hello world!%d", a); }; //执行 testblock(); retu