pragma mark Block注意事项
pragma mark 概念
/**
1.为什么不加 __block不能在block中修改外界变量的值 (值传递)
2.为什么加 __block能在block中修改外界变量的值 (地址传递)
3.block 是 存储在堆中 还是 栈中 (默认在栈,copy到堆)
4.如果在block中访问了外界的对象, 一定要给对象加上 __block, 只要加上了__block, 哪怕block 在堆中 , 也不会对外界的对象 进行retain操作
*/
pragma mark 代码
#import <Foundation/Foundation.h>
#pragma mark 类
#import "Person.h"
#pragma mark main函数
int main(int argc, const char * argv[])
{
#warning 1.block中 可以访问外面的变量
/*
int a = 10;
void (^myBlock)() = ^{
NSLog(@"a = %i",a);
};
// 调用block
myBlock();
*/
#warning 2.block 中 可以定义和外界 同名的变量, 并且如果 在block 中定义了和外名同名的变量, 在block中访问的事block中的变量
/*
int a = 10;
void (^myBlock)() = ^{
int a = 20;
NSLog(@"a = %i",a);
};
// 调用block
myBlock();
*/
#warning 3.block 默认情况下, 不可以在block中修改外界变量的值
// 因为block中的变量 和 外界的变量 并不是同一个变量
// 如果block中 访问了外界的变量, block 会将外界的变量 拷贝一份到堆内存中
// 因为block中使用的外界变量 是 copy的, 所以在调用之前 修改 外界变量的值, 不会影响到block 中 copy的值
#pragma mark code
/*
int a = 10;
NSLog(@"&a = %p",&a); // 0x7fff5fbff7dc
void (^myBlock)() = ^{
// a = 50;
NSLog(@"&a = %p",&a); // 0x1005002f0
NSLog(@"a = %i",a);
};
a = 20;
// 调用block
myBlock();
*/
#warning 4.block 不默认情况下, 可以在block中修改外界变量的值
// 如果想在block中 修改外界变量的值, 必须在外界变量 前面加上 __block
// 如果在block中 修改了外界变量的值, 会影响外界变量的值
#pragma mark code
/*
__block int a = 10;
NSLog(@"&a = %p",&a); // 0x7fff5fbff7d8
void (^myBlock)() = ^{
a = 50;
NSLog(@"&a = %p",&a); // 0x103200278
NSLog(@"a = %i",a);
};
// 调用block
myBlock();
NSLog(@"a = %i",a);
*/
#pragma mark 5.深入了解 为什么添加__block 就可以修改外界变量的值
/**
将.m文件 转换成c++文件(为什么调用方法 称为 发消息)
通过终端
到当前的路径 cc -rewrite-objc main.m 此时 多了一个文件
打开.cpp
NSXPCListenerEndpoint 搜索 从最后一个前面的代码全部删除
*/
#warning 1.为什么不加 __block不能在block中修改外界变量的值 (值传递)
#pragma mark 1.code
/*
int a = 10;
void (^myBlock)() = ^{
// a = 20;
NSLog(@"a = %i",a);
};
myBlock();
*/
#pragma mark cpp code
/**
// __main_block_impl_0 这一块是一个结构体
int a = 10; // 如果没有添加 __block是值传递
void (*myBlock)() = &__main_block_impl_0(__main_block_func_0, &__main_block_desc_0_DATA, a)); // 基本数据类型 作为函数参数传递 是值传递 在内部修改 不会影响外部
(myBlock)->FuncPtr)(myBlock);
*/
#warning 2.为什么加 __block能在block中修改外界变量的值 (地址传递)
#pragma mark 2.code
/*
__block int a = 10;
void (^myBlock)() = ^{
a = 20;
NSLog(@"a = %i",a);
};
myBlock();
*/
#pragma mark cpp code
/**
// __main_block_impl_0 这一块是一个结构体
// &a 这里传递的是一个 地址
// a = 10; // 如果加上 __block 之后 就是地址传递, 所以可以在block中 修改外界变量的值
// void (*myBlock)() = &__main_block_impl_0(__main_block_func_0, &__main_block_desc_0_DATA, &a, 570425344));
*/
#pragma mark 6.block 是 存储在堆中 还是 栈中 (默认在栈,copy到堆)
// 默认情况下 block存储在栈中, 如果对block进行一个copy操作,block会转移到堆中
// 如果block在 栈中, block中访问了外界的对象, 那么不会对 对象进行retain操作。
// 但是block在 堆中, block中访问了外界的对象, 那么会对 外界的对象进行一次 retain
// 如果在block中访问了外界的对象, 一定要给对象加上 __block, 只要加上了__block, 哪怕block 在堆中 , 也不会对外界的对象 进行retain操作
// Person *p = [[Person alloc]init]; // 1
__block Person *p = [[Person alloc]init]; // 1
NSLog(@"retainCount = %lu",[p retainCount]); // 1
void (^myBlock)() = ^{
NSLog(@"a = %@",p); // 1 没有加上 __block 是2
NSLog(@"block retainCount = %lu",[p retainCount]); // 1
};
Block_copy(myBlock); // 2 这里也会对外界的对象进行一次retain操作
myBlock();
[p release]; // 0 没有加上 __block 是1 出现内存泄露
return 0;
}
#pragma mark 3. 添加__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; // by ref
// __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;
// }
//};
//static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
// __Block_byref_a_0 *a = __cself->a; // bound by ref
//
// (a->__forwarding->a) = 20;
// NSLog((NSString *)&__NSConstantStringImpl__var_folders_7r_m33tlwsx3w79b9r0btsyv8q80000gp_T_main_e0c860_mi_0,(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[])
//{
// a = 10;
// void (*myBlock)() = &__main_block_impl_0(__main_block_func_0, &__main_block_desc_0_DATA, &a, 570425344));
// return 0;
//}
//static struct IMAGE_INFO { unsigned version; unsigned flag; } _OBJC_IMAGE_INFO = { 0, 2 };
#pragma mark 1.没有添加__block 反编译文件 修改完毕
/*
修改完毕的
.cpp
struct __main_block_impl_0 {
struct __block_impl impl;
struct __main_block_desc_0* Desc;
int 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;
}
};
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
int a = __cself->a; // bound by copy
NSLog((NSString *)&__NSConstantStringImpl__var_folders_7r_m33tlwsx3w79b9r0btsyv8q80000gp_T_main_3b2773_mi_0,a);
}
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, const char * argv[])
{
int a = 10;
void (*myBlock)() = &__main_block_impl_0(__main_block_func_0, &__main_block_desc_0_DATA, a));
(myBlock)->FuncPtr)(myBlock);
return 0;
}
static struct IMAGE_INFO { unsigned version; unsigned flag; } _OBJC_IMAGE_INFO = { 0, 2 };
*/
#pragma mark 2.__block反编译文件 未修改的
/*
struct __main_block_impl_0 {
struct __block_impl impl;
struct __main_block_desc_0* Desc;
int 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;
}
};
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
int a = __cself->a; // bound by copy
NSLog((NSString *)&__NSConstantStringImpl__var_folders_7r_m33tlwsx3w79b9r0btsyv8q80000gp_T_main_3b2773_mi_0,a);
}
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, const char * argv[])
{
int a = 10;
void (*myBlock)() = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, a));
((void (*)(__block_impl *))((__block_impl *)myBlock)->FuncPtr)((__block_impl *)myBlock);
return 0;
}
static struct IMAGE_INFO { unsigned version; unsigned flag; } _OBJC_IMAGE_INFO = { 0, 2 };
*/
Person.h //人类
#import <Foundation/Foundation.h>
@interface Person : NSObject
@end
Person.m
#import "Person.h"
@implementation Person
- (void)dealloc
{
NSLog(@"%s",__func__);
[super dealloc];
}
@end