iOS之获取Block retain的objects

Block管理Objective-C对象实例的原理


Block的实现结构体见如下图所示,Block对于捕获的Objective-C对象实例,会在Block实现的结构体中创建一个变量指向Objective-C对象实例,当Block将要释放时,会调用dispose_helper函数,该函数会调用所有需要进行内存管理的所捕获的对象,如Block__block变量、__attribute__((NSObject))变量或有constructor/destructorC++ const对象。

获取Block retain的Objective-C对象实例


所以,怎么能够拿到retainObjective-C对象实例呢,方法为创建fake对象,来模拟捕获的Objective-C对象实例,然后我们程序来调用Blockdispose_helper方法(dispose_helper方法接收一个参数,值为Block的指针),该方法会调用对象实例的release方法,我们只需要在fake对象中实现release方法,如果release方法被调用,所以该fake对象对应的真实变量为Objective-C对象实例。

那么需要创建多少个fake对象呢,首先,Objective-C对象实例在Blockstruct中的位置是指针对齐的,所以我们可以获取Block结构体的大小,除以指针的大小取上即为需要创建的fake对象的数量,Block结构体的size可以通过block->descriptor->size来获取。

得到需要创建fake对象的数量count后,创建一个数组,再创建countfake对象,将数组指针传入dispose_helper即可。对于调用了release方法的对象,记录其索引值,通过访问block[index]即可拿到真正的Objective-C对象实例。

注意


如上所说的捕获的Objective-C对象实例,不包括使用__block创建的实例,因为使用__block创建的变量,会加一层间接层,并不会在Block结构体中创建指向实例对象的变量,而是指向另一个间接层结构体。

附录


  1. https://clang.llvm.org/docs/Block-ABI-Apple.html
  2. https://github.com/mikeash/Circle/blob/master/Circle/CircleIVarLayout.m