# 【译】《A look inside blocks: Episode 1》

## 基础

block就是下面这样的：

``````void(^block)(void) = ^{
NSLog(@"I'm a block!");
};

``````void(^block)(int a) = ^{
NSLog(@"I'm a block! a = %i", a);
};

``````int(^block)(void) = ^{
NSLog(@"I'm a block!");
return 1;
};

``````int a = 1;
void(^block)(void) = ^{
NSLog(@"I'm a block! a = %i", a);
};

## 探究一个简单的例子

``````#import <dispatch/dispatch.h>

typedef void(^BlockA)(void);

__attribute__((noinline))
void runBlockA(BlockA block) {
block();
}

void doBlockA() {
BlockA block = ^{
// Empty block
};
runBlockA(block);
}

``````.globl  _runBlockA
.align  2
.code   16                      @ @runBlockA
.thumb_func     _runBlockA
_runBlockA:
@ BB#0:
ldr     r1, [r0, #12]
bx      r1

``````.globl  _doBlockA
.align  2
.code   16                      @ @doBlockA
.thumb_func     _doBlockA
_doBlockA:
movw    r0, :lower16:(___block_literal_global-(LPC1_0+4))
movt    r0, :upper16:(___block_literal_global-(LPC1_0+4))
LPC1_0:
b.w     _runBlockA

``````.align  2                       @ @__block_literal_global
___block_literal_global:
.long   __NSConcreteGlobalBlock
.long   1342177280              @ 0x50000000
.long   0                       @ 0x0
.long   ___doBlockA_block_invoke_0
.long   ___block_descriptor_tmp

``````    .align  2
.code   16                      @ @__doBlockA_block_invoke_0
.thumb_func     ___doBlockA_block_invoke_0
___doBlockA_block_invoke_0:
bx      lr

.section        __DATA,__const
.align  2                       @ @__block_descriptor_tmp
___block_descriptor_tmp:
.long   0                       @ 0x0
.long   20                      @ 0x14
.long   L_.str
.long   L_OBJC_CLASS_NAME_

.section        __TEXT,__cstring,cstring_literals
L_.str:                                 @ @.str
.asciz   "v4@?0"

.section        __TEXT,__objc_classname,cstring_literals
L_OBJC_CLASS_NAME_:                     @ @"\\01L_OBJC_CLASS_NAME_"
.asciz   "\\001"

## 源码不就推理出来了？

``````struct Block_descriptor {
unsigned long int reserved;
unsigned long int size;
void (*copy)(void *dst, void *src);
void (*dispose)(void *);
};

struct Block_layout {
void *isa;
int flags;
int reserved;
void (*invoke)(void *, ...);
struct Block_descriptor *descriptor;
/* Imported variables. */
};

`Block_layout`中的`isa`很值得关注，因为他可能就是`_NSConcreteGlobalBlock`。而且也可能是一个block如何可以具有一个Objective-C对象行为的关键。如果`_NSConcreteGlobalBlock`是一个`类`，那么Objective-C的消息传递机制系统很乐意将一个block对象当做一个普通对象来处理。这与无缝桥接（toll-free bridging）工作机制很相似。关于这方面(toll-free bridging)的更多信息，请阅读Mike Ash's的优秀博文

``````#import <dispatch/dispatch.h>

__attribute__((noinline))
void runBlockA(struct Block_layout *block) {
block->invoke();
}

void block_invoke(struct Block_layout *block) {
// Empty block function
}

void doBlockA() {
struct Block_descriptor descriptor;
descriptor->reserved = 0;
descriptor->size = 20;
descriptor->copy = NULL;
descriptor->dispose = NULL;

struct Block_layout block;
block->isa = _NSConcreteGlobalBlock;
block->flags = 1342177280;
block->reserved = 0;
block->invoke = block_invoke;
block->descriptor = descriptor;

runBlockA(&block);
}

iOS