1.完整写法
void(^ blockName)(arg)=void^(arg){};
2.block 可以使用截取到的自动变量,但是不允许修改重新赋值。
例:
int m=3;
char* str1="str1";
void(^block1)(void)=^(){
NSLog(@"%d,%s",m,str1);
};
m=6;
str1="变化";
block1();
OUTPUT:3,str1
若要修改自动变量的值必须添加__block
block以及截取自动变量的本质
使用clang -rewrite-objc 命令转化上面的代码
/**
__block_impl 结构体
*/
struct __block_impl {
void *isa;
int Flags;
int Reserved;
void *FuncPtr;
};
/**
__main_block_impl_0结构体
*/
struct __main_block_impl_0 {
//__block_impl 结构体
struct __block_impl impl;
//__main_block_desc_0 结构体
struct __main_block_desc_0* Desc;
int m;
char *str1;
__main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int _m, char *_str1, int flags=0) : m(_m), str1(_str1) {
//_NSConcreteStackBlock 用于初始化__block_impl 结构体的isa成员 表明该block类型为NSConcreteStackBlock
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
/**
1.变换后的block1 被作为简单的C语言函数来处理
2.函数中的__cself 相当于OC中的self 这里指代__main_block_impl_0结构体的指针
^(){
int n=m+3;
printf("%d,%s",m,str1);
};
*/
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
int m = __cself->m; // bound by copy 自动变量被保存到Block的结构体实例中。需要注意的是Block中不能直接使用C语言数据类型的自动变量,原因是C语言不允许这种操作
char *str1 = __cself->str1; // bound by copy
int n=m+3;
printf("%d,%s",m,str1);
}
/**
__main_block_desc_0 结构体
*/
static struct __main_block_desc_0 {
size_t reserved;
size_t Block_size;
} __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0)};
int main(int argc, char * argv[]) {
int m=3;
char* str1="str1";
/*
void(^block1)(void)=^(){
int n=m+3;
printf("%d,%s",m,str1);
};
*/
void(*block1)(void)=((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, m, str1));
m=6;
str1="变化";
((void (*)(__block_impl *))((__block_impl *)block1)->FuncPtr)((__block_impl *)block1);
}
_ _block 修饰的变量 本质
例:__block int m=3;此时m会被转化为__Block_byref_m_0结构体
struct __Block_byref_m_0 {
void *__isa;
__Block_byref_m_0 *__forwarding; (指向m:__Block_byref_m_0本身)
int __flags;
int __size;
int m;// m=3
};
__Block_byref_m_0 *__forwarding;//持有指向该实例自身的指针,通过成员变量__forwarding访问成员变量val
解决循环引用问题
__weak typeof(_tom) weak = _tom;
_tom.block = ^{
__strong typeof(weak) strong = weak;
};
__weak : 打破强引用链 即_tom对象强引用block对象,block对象强引用_tom对象
__strong:在block中声明了一个局部变量,暂时“强引用”_tom对象,由于block并不会强引用block内部声明的__strong修饰的局部变量。所以这样即保证了在block调用时_tom对象存在又不会造成循环引用。