typedef void(^GHBlock)(void);
底层源码
typedef void(*GHBlock)(void);
struct __main_block_impl_0 {
struct __block_impl impl;
struct __main_block_desc_0* Desc;
GHPerson *person;
__main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, GHPerson *_person, int flags=0) : person(_person) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
GHPerson *person = __cself->person; // bound by copy
NSLog((NSString *)&__NSConstantStringImpl__var_folders_5r_8b0nqlv12v5ftv77b9t0v04h0000gn_T_main_5b5b91_mi_0,((int (*)(id, SEL))(void *)objc_msgSend)((id)person, sel_registerName("age")));
}
static void __main_block_copy_0(struct __main_block_impl_0*dst, struct __main_block_impl_0*src) {_Block_object_assign((void*)&dst->person, (void*)src->person, 3/*BLOCK_FIELD_IS_OBJECT*/);}
static void __main_block_dispose_0(struct __main_block_impl_0*src) {_Block_object_dispose((void*)src->person, 3/*BLOCK_FIELD_IS_OBJECT*/);}
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[]) {
/* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool;
GHPerson *person = ((GHPerson *(*)(id, SEL))(void *)objc_msgSend)((id)((GHPerson *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("GHPerson"), sel_registerName("alloc")), sel_registerName("init"));
((void (*)(id, SEL, int))(void *)objc_msgSend)((id)person, sel_registerName("setAge:"), 10);
((void (*)(id, SEL, GHBlock _Nonnull))(void *)objc_msgSend)((id)person, sel_registerName("setBlock:"), ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, person, 570425344)));
NSLog((NSString *)&__NSConstantStringImpl__var_folders_5r_8b0nqlv12v5ftv77b9t0v04h0000gn_T_main_5b5b91_mi_1);
}
return 0;
}
block强引用person
person强引用block
block循环引用解决方案:
__weak:使用弱引用解除循环引用,不会产生强引用,指向的对象销毁时,会自动让指针置为nil。
__block:此种解决方案必须要调用block
__unsafe_unretained:不会产生强引用,不安全,指向的对象销毁时,指针存储的地址值不变。
__unsafe_unretained typeof(person) weakPerson = person;
源码
GHPerson *person = [[GHPerson alloc]init];
person.age = 10;
// [person test];
// __unsafe_unretained:不会产生强引用
__unsafe_unretained typeof(person) weakPerson = person;
person.block = ^{
NSLog(@"age is %d",weakPerson.age);
};
//
NSLog(@"1111111112");
转换后的底层源码
我们可以看到,typeof (person) weakPerson;这里只是一个类型判别,并不是向上面的GHPerson *person;一样。
typedef void(*GHBlock)(void);
struct __main_block_impl_0 {
struct __block_impl impl;
struct __main_block_desc_0* Desc;
typeof (person) weakPerson;
__main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, typeof (person) _weakPerson, int flags=0) : weakPerson(_weakPerson) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
typeof (person) weakPerson = __cself->weakPerson; // bound by copy
NSLog((NSString *)&__NSConstantStringImpl__var_folders_5r_8b0nqlv12v5ftv77b9t0v04h0000gn_T_main_4419cf_mi_0,((int (*)(id, SEL))(void *)objc_msgSend)((id)weakPerson, sel_registerName("age")));
}
static void __main_block_copy_0(struct __main_block_impl_0*dst, struct __main_block_impl_0*src) {_Block_object_assign((void*)&dst->weakPerson, (void*)src->weakPerson, 3/*BLOCK_FIELD_IS_OBJECT*/);}
static void __main_block_dispose_0(struct __main_block_impl_0*src) {_Block_object_dispose((void*)src->weakPerson, 3/*BLOCK_FIELD_IS_OBJECT*/);}
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[]) {
/* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool;
GHPerson *person = ((GHPerson *(*)(id, SEL))(void *)objc_msgSend)((id)((GHPerson *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("GHPerson"), sel_registerName("alloc")), sel_registerName("init"));
((void (*)(id, SEL, int))(void *)objc_msgSend)((id)person, sel_registerName("setAge:"), 10);
__attribute__((objc_ownership(none))) typeof(person) weakPerson = person;
((void (*)(id, SEL, GHBlock _Nonnull))(void *)objc_msgSend)((id)person, sel_registerName("setBlock:"), ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, weakPerson, 570425344)));
NSLog((NSString *)&__NSConstantStringImpl__var_folders_5r_8b0nqlv12v5ftv77b9t0v04h0000gn_T_main_4419cf_mi_1);
}
return 0;
}
__block:通过调用block来解决循环方案
源码
__block GHPerson *person = [[GHPerson alloc]init];
person.age = 10;
person.block = ^{
NSLog(@"age is %d",person.age);
person = nil;
};
person.block();
转换后的cpp底层代码
typedef void(*GHBlock)(void);
struct __Block_byref_person_0 {
void *__isa;
__Block_byref_person_0 *__forwarding;
int __flags;
int __size;
void (*__Block_byref_id_object_copy)(void*, void*);
void (*__Block_byref_id_object_dispose)(void*);
GHPerson *person;
};
struct __main_block_impl_0 {
struct __block_impl impl;
struct __main_block_desc_0* Desc;
__Block_byref_person_0 *person; // by ref
__main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, __Block_byref_person_0 *_person, int flags=0) : person(_person->__forwarding) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
__Block_byref_person_0 *person = __cself->person; // bound by ref
NSLog((NSString *)&__NSConstantStringImpl__var_folders_5r_8b0nqlv12v5ftv77b9t0v04h0000gn_T_main_94729c_mi_0,((int (*)(id, SEL))(void *)objc_msgSend)((id)(person->__forwarding->person), sel_registerName("age")));
(person->__forwarding->person) = __null;
}
static void __main_block_copy_0(struct __main_block_impl_0*dst, struct __main_block_impl_0*src) {_Block_object_assign((void*)&dst->person, (void*)src->person, 8/*BLOCK_FIELD_IS_BYREF*/);}
static void __main_block_dispose_0(struct __main_block_impl_0*src) {_Block_object_dispose((void*)src->person, 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[]) {
/* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool;
__attribute__((__blocks__(byref))) __Block_byref_person_0 person = {(void*)0,(__Block_byref_person_0 *)&person, 33554432, sizeof(__Block_byref_person_0), __Block_byref_id_object_copy_131, __Block_byref_id_object_dispose_131, ((GHPerson *(*)(id, SEL))(void *)objc_msgSend)((id)((GHPerson *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("GHPerson"), sel_registerName("alloc")), sel_registerName("init"))};
((void (*)(id, SEL, int))(void *)objc_msgSend)((id)(person.__forwarding->person), sel_registerName("setAge:"), 10);
((void (*)(id, SEL, GHBlock _Nonnull))(void *)objc_msgSend)((id)(person.__forwarding->person), sel_registerName("setBlock:"), ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, (__Block_byref_person_0 *)&person, 570425344)));
((GHBlock (*)(id, SEL))(void *)objc_msgSend)((id)(person.__forwarding->person), sel_registerName("block"))();
}
return 0;
}
需要注意的是:MRC环境下不支持若指针的解决方案,既不支持__weak,而且使用__block不会产生强引用。