赞
踩
首先来看block结构体对象Block_layout
(等同于clang编译出来的__Block_byref_a_0
)
#define BLOCK_DESCRIPTOR_1 1 struct Block_descriptor_1 { uintptr_t reserved; uintptr_t size; }; #define BLOCK_DESCRIPTOR_2 1 struct Block_descriptor_2 { // requires BLOCK_HAS_COPY_DISPOSE BlockCopyFunction copy; BlockDisposeFunction dispose; }; #define BLOCK_DESCRIPTOR_3 1 struct Block_descriptor_3 { // requires BLOCK_HAS_SIGNATURE const char *signature; const char *layout; // contents depend on BLOCK_HAS_EXTENDED_LAYOUT }; struct Block_layout { void *isa; volatile int32_t flags; // contains ref count int32_t reserved; BlockInvokeFunction invoke; struct Block_descriptor_1 *descriptor; // // imported variables };
其中Block_layout
是基础的block结构空间,而部分block则拥有Block_descriptor_2
和Block_descriptor_3
结构,其中的flags
标识记录了一些信息
Block_descriptor_2
和Block_descriptor_3
结构这句话又该怎么去理解呢?请看下面的解释static struct Block_descriptor_2 * _Block_descriptor_2(struct Block_layout *aBlock) { if (! (aBlock->flags & BLOCK_HAS_COPY_DISPOSE)) return NULL; uint8_t *desc = (uint8_t *)aBlock->descriptor; desc += sizeof(struct Block_descriptor_1); return (struct Block_descriptor_2 *)desc; } static struct Block_descriptor_3 * _Block_descriptor_3(struct Block_layout *aBlock) { if (! (aBlock->flags & BLOCK_HAS_SIGNATURE)) return NULL; uint8_t *desc = (uint8_t *)aBlock->descriptor; desc += sizeof(struct Block_descriptor_1); if (aBlock->flags & BLOCK_HAS_COPY_DISPOSE) { desc += sizeof(struct Block_descriptor_2); } return (struct Block_descriptor_3 *)desc; }
aBlock->flags & BLOCK_HAS_COPY_DISPOSE
满足,则_Block_descriptor_2
存在,反之则block没有_Block_descriptor_2
这个结构
_Block_descriptor_2
可以通过Block_descriptor_1
内存偏移得到aBlock->flags & BLOCK_HAS_SIGNATURE
满足,则_Block_descriptor_3
存在
_Block_descriptor_3
可以通过Block_descriptor_2
内存偏移得到决定这两个结构是否存在的绝对因素其实就是Block_layout
的flags
// Values for Block_layout->flags to describe block objects
enum {
BLOCK_DEALLOCATING = (0x0001), // runtime
BLOCK_REFCOUNT_MASK = (0xfffe), // runtime
BLOCK_NEEDS_FREE = (1 << 24), // runtime
BLOCK_HAS_COPY_DISPOSE = (1 << 25), // compiler
BLOCK_HAS_CTOR = (1 << 26), // compiler: helpers have C++ code
BLOCK_IS_GC = (1 << 27), // runtime
BLOCK_IS_GLOBAL = (1 << 28), // compiler
BLOCK_USE_STRET = (1 << 29), // compiler: undefined if !BLOCK_HAS_SIGNATURE
BLOCK_HAS_SIGNATURE = (1 << 30), // compiler
BLOCK_HAS_EXTENDED_LAYOUT=(1 << 31) // compiler
};
接下来就用汇编来看看block中的签名
_ NSGlobalBlock__签名(_ Block_copy进入时)
方法签名在lldb调试中使用po命令,查看block对象的地址
通过方法签名,可以在运行时获取 Block 的参数和返回值类型,帮助程序在调用 Block 时正确地处理数据。
通过方法签名,你可以在运行时动态地调用不同的方法或函数,而不需要提前确定要调用的具体方法。
回调机制:方法签名使得你可以将方法或函数作为参数传递给其他方法或函数,从而实现回调机制。
反射机制:方法签名在反射机制中发挥重要作用,它允许程序在运行时获取方法的信息,如方法名称、参数个数、参数类型、返回值类型等。
适配器模式:在设计模式中,方法签名的使用有助于实现适配器模式,从而使不同接口的方法能够相互调用。
方法签名的含义可查看[[Type Encodings]]
v
: 返回值是 void
类型。
8@?
: 参数部分的编码。
8
代表参数的个数。@
代表第一个参数是一个对象类型。?
代表第二个参数是一个 Block 类型。0
代表没有其他参数。NSMallocBlock
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。