void * _NSConcreteStackBlock[32] = { 0 };
void * _NSConcreteMallocBlock[32] = { 0 };
void * _NSConcreteAutoBlock[32] = { 0 };
void * _NSConcreteFinalizingBlock[32] = { 0 };
void * _NSConcreteGlobalBlock[32] = { 0 };
void * _NSConcreteWeakBlockVariable[32] = { 0 };
未捕获外部变量,默认是__NSGlobalBlock__
类型。
dispatch_block_t block =^{};
dispatch_block_t block_1 =[^{} copy];
在mrc
下捕获外部变量,则是栈block
,在arc
情况下,系统自动执行copy
,block
类型变为__NSMallocBlock__
,如果是static
或者全局变量则不需要捕获。因为全局变量在全局都可以访问到。
int a = 0;
dispatch_block_t block2 =^{
NSLog(@"%d",a);
};
在arc
编译环境下,系统自动管理block_copy
将stackBlock
类型变为__NSMallocBlock__
,将block copy
之后赋值给强引用的指针。
int a = 0;
dispatch_block_t block2 =^{
NSLog(@"%d",a);
};
clang -x objective-c -rewrite-objc -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk main.m
生成的结构体block内部直接生成了包含外部变量,在构造函数中复制给结构体的变量a。
int main(int argc, const char * argv[]) {
int a = 10;
void (^block)(void)=^{
printf("fgyong.cn %d",a);
};
block();
return 0;
}
============================clang 之后的代码=========================
struct __main_block_impl_0 {
struct __block_impl impl;
struct __main_block_desc_0* Desc;
int a;//属性
// 构造函数 自动复制给a=_a
__main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int _a, int flags=0) : a(_a) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
int main(int argc, const char * argv[]) {
int a = 10;
// 步骤A 构造结构体
void (*block)(void)=(__main_block_impl_0(__main_block_func_0, &__main_block_desc_0_DATA, a));
// 步骤B 执行block 看下面C
block->FuncPtr((__block_impl *)block);
return 0;
}
//步骤C 当执行则取出来结构体中存储的a值。
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
int a = __cself->a; // 值拷贝 只能取出来不能赋值。
printf("fgyong.cn %d",a);
}
__block修饰的变量的地址被block结构体保存,地址拷贝,可以对对象进行赋值。
struct __Block_byref_a_0 {
void *__isa;
__Block_byref_a_0 *__forwarding;//指向自己的地址
int __flags;
int __size;//占用空间大小
int a;//变量的值
};
struct __main_block_impl_0 {
struct __block_impl impl;
struct __main_block_desc_0* Desc;
__Block_byref_a_0 *a; // 记录外部变量的结构体的地址,该结构体记录了变量的值与地址
// 构造函数将 __block修饰的a的地址保存到了block的结构体中。
__main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, __Block_byref_a_0 *_a, int flags=0) : a(_a->__forwarding) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
// 执行block
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
__Block_byref_a_0 *a = __cself->a;//指针拷贝 可以赋值
printf("fgyong.cn %d",(a->__forwarding->a));
}
static void __main_block_copy_0(struct __main_block_impl_0*dst, struct __main_block_impl_0*src) {_Block_object_assign((void*)&dst->a, (void*)src->a, 8/*BLOCK_FIELD_IS_BYREF*/);}
static void __main_block_dispose_0(struct __main_block_impl_0*src) {_Block_object_dispose((void*)src->a, 8/*BLOCK_FIELD_IS_BYREF*/);}
static struct __main_block_desc_0 {
size_t reserved;
size_t Block_size;
void (*copy)(struct __main_block_impl_0*, struct __main_block_impl_0*);
void (*dispose)(struct __main_block_impl_0*);
} __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0), __main_block_copy_0, __main_block_dispose_0};
int main(int argc, const char * argv[]) {
__attribute__((__blocks__(byref))) __Block_byref_a_0 a =
{(void*)0,
(__Block_byref_a_0 *)&a,
0,
sizeof(__Block_byref_a_0),
10};
void (*block)(void)=(__main_block_impl_0(__main_block_func_0, __main_block_desc_0_DATA,&a, 570425344));
block->FuncPtr((__block_impl *)block);
return 0;
}
GCD
中dispatch_after/dispatch_queue
会强引用self
,影响生命周期,一般不会内存泄露,因为只是GCD
引用了self
,self
并无引用GCD
。
// 3秒后任务结束 再释放 self
queue=dispatch_queue_create("com.fgyong.cn", DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, ^{
sleep(3);
dispatch_async(dispatch_get_main_queue(), ^{
self.view.backgroundColor=[UIColor grayColor];
});
});
UIView
没有强引用v
,不影响生命周期,没有强引用。属于非逃逸block
,在执行的所有者任务之前结束了block
的引用,例如 Masory
// 非逃逸 block 执行任务的对象结束之前已经执行了block,则是非逃逸
// 逃逸 block 是在对象执行block完毕,自己生命周期结束,则是逃逸。
// 而且 是stackBlock 类型不会对auto变量前引用
[UIView animateWithDuration:3
animations:^{
self.view.backgroundColor=[UIColor grayColor];
}];