block的本质上也是一个OC对象,它内部也有一个isa指针
block是封装了函数调用以及函数调用环境的OC对象
结构示意图
变量捕获示意图
为了保证block内部能够正常访问外部的变量,block有变量捕获机制
示例代码
============================== 原始代码 ==============================
@interface TBPerson : NSObject
@property (nonatomic, strong) NSString *name;
@end
@implementation TBPerson
@end
@interface ViewController ()
@end
@implementation ViewController
static const NSInteger height = 10;
static const TBPerson *person;
- (void)viewDidLoad {
[super viewDidLoad];
person = [[TBPerson alloc] init];
person.name = @"111";
int age = 20;
TBPerson *person1 = [[TBPerson alloc] init];
person1.name = @"222";
static const int number = 30;
static const TBPerson *person2;
person2 = [[TBPerson alloc] init];
person2.name = @"333";
__weak TBPerson *person3 = person1;
person3.name = @"444";
void (^block) (void) = ^{
NSLog(@"%ld",(long)height);
NSLog(@"%@",person.name);
NSLog(@"%ld",(long)age);
NSLog(@"%@",person1.name);
NSLog(@"%ld",(long)number);
NSLog(@"%@",person2.name);
NSLog(@"%@",person3.name);
};
block();
}
============================== 使用clang转换为C++猜测底层实现 ==============================
void (*block) (void) = ((void (*)())&__ViewController__viewDidLoad_block_impl_0((void *)__ViewController__viewDidLoad_block_func_0,
&__ViewController__viewDidLoad_block_desc_0_DATA,
age,person1, &number, &person2, person3, 570425344));
((void (*)(__block_impl *))((__block_impl *)block)->FuncPtr)((__block_impl *)block);
static const NSInteger height = 10;
static const TBPerson *person;
struct __ViewController__viewDidLoad_block_impl_0 {
struct __block_impl impl;
struct __ViewController__viewDidLoad_block_desc_0* Desc;
int age;
TBPerson *__strong person1;
const int *number;
const TBPerson *__strong *person2;
TBPerson *__weak person3;
__ViewController__viewDidLoad_block_impl_0(void *fp, struct __ViewController__viewDidLoad_block_desc_0 *desc, int _age, TBPerson *__strong _person1, const int *_number, const TBPerson *__strong *_person2, TBPerson *__weak _person3, int flags=0) : age(_age), person1(_person1), number(_number), person2(_person2), person3(_person3) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
struct __block_impl {
void *isa;
int Flags;
int Reserved;
void *FuncPtr;
};
static struct __ViewController__viewDidLoad_block_desc_0 {
size_t reserved;
size_t Block_size;
void (*copy)(struct __ViewController__viewDidLoad_block_impl_0*, struct __ViewController__viewDidLoad_block_impl_0*);
void (*dispose)(struct __ViewController__viewDidLoad_block_impl_0*);
} __ViewController__viewDidLoad_block_desc_0_DATA = {
0,
sizeof(struct __ViewController__viewDidLoad_block_impl_0),
__ViewController__viewDidLoad_block_copy_0,
__ViewController__viewDidLoad_block_dispose_0
};
static void __ViewController__viewDidLoad_block_copy_0(struct __ViewController__viewDidLoad_block_impl_0*dst, struct __ViewController__viewDidLoad_block_impl_0*src) {
_Block_object_assign((void*)&dst->person1, (void*)src->person1, 3);
_Block_object_assign((void*)&dst->person2, (void*)src->person2, 3);
_Block_object_assign((void*)&dst->person3, (void*)src->person3, 3);
}
static void __ViewController__viewDidLoad_block_dispose_0(struct __ViewController__viewDidLoad_block_impl_0*src) {
_Block_object_dispose((void*)src->person1, 3);
_Block_object_dispose((void*)src->person2, 3);
_Block_object_dispose((void*)src->person3, 3);
}
static void __ViewController__viewDidLoad_block_func_0(struct __ViewController__viewDidLoad_block_impl_0 *__cself) {
int age = __cself->age;
TBPerson *__strong person1 = __cself->person1;
const int *number = __cself->number;
const TBPerson *__strong *person2 = __cself->person2;
TBPerson *__weak person3 = __cself->person3;
NSLog((NSString *)&__NSConstantStringImpl__var_folders_lx_q2n5w01149j15zhtyt93nzpr0000gn_T_ViewController_47fdc6_mi_4,(long)height);
NSLog((NSString *)&__NSConstantStringImpl__var_folders_lx_q2n5w01149j15zhtyt93nzpr0000gn_T_ViewController_47fdc6_mi_5,((NSString *(*)(id, SEL))(void *)objc_msgSend)((id)person, sel_registerName("name")));
NSLog((NSString *)&__NSConstantStringImpl__var_folders_lx_q2n5w01149j15zhtyt93nzpr0000gn_T_ViewController_47fdc6_mi_6,(long)age);
NSLog((NSString *)&__NSConstantStringImpl__var_folders_lx_q2n5w01149j15zhtyt93nzpr0000gn_T_ViewController_47fdc6_mi_7,((NSString *(*)(id, SEL))(void *)objc_msgSend)((id)person1, sel_registerName("name")));
NSLog((NSString *)&__NSConstantStringImpl__var_folders_lx_q2n5w01149j15zhtyt93nzpr0000gn_T_ViewController_47fdc6_mi_8,(long)(*number));
NSLog((NSString *)&__NSConstantStringImpl__var_folders_lx_q2n5w01149j15zhtyt93nzpr0000gn_T_ViewController_47fdc6_mi_9,((NSString *(*)(id, SEL))(void *)objc_msgSend)((id)person2, sel_registerName("name")));
NSLog((NSString *)&__NSConstantStringImpl__var_folders_lx_q2n5w01149j15zhtyt93nzpr0000gn_T_ViewController_47fdc6_mi_10,((NSString *(*)(id, SEL))(void *)objc_msgSend)((id)person3, sel_registerName("name")));
}
============================== block内部访问了对象类型的auto变量时 总结==============================
@end
PS 此文为学习 李明杰 老师的 iOS底层原理课程 所写笔记