- 不要等到明天,明天太遥远,今天就行动。
须读:看完该文章你能做什么?
1.了解block的底层原理
2.什么是____strong__
什么是____weak__
3.什么时候使用__block
学习前:你必须会什么?(在这里我已经默认你具备C语言的基础了)
1.block的使用
一、本章笔记
一、
1.block中可以访问外面的变量
2.block中可以定义和外界同名的变量, 并且如果在block定义了和外界同名的变量,在block中访问的是block中的变量
3.默认情况下,不可以在block中修改外界变量的值
4.不默认情况下,加上__block 修饰符 可以在block中修改外界变量的值
二、
1.验证为什么不加 __block 不能在block中修改外界变量的值
2.验证而加了 __block 就可以在block中修改外界变量的值
>步骤
1.通过Clang指令来获取系统编译的C++代码
2.1.cd到指定文件路径 ,然后通过cc -rewrite-objc main.m
3.获取.cpp文件.跳到最后的104800行左右找到main.m函数
找到对应的代码 进行对比(一个是值传递,一个是地址传递)
三、
block是存储在堆中(copy情况下) 还是栈中(默认情况下)
如果在block 中访问了外界的对象,一定要给对象加上 __block, 只要加上了 __block 哪怕block在堆中,也不会对外界的兑现进行retain操作
二、code
main.m
#pragma mark 15-Block注意事项
#pragma mark 概念
#pragma mark - 代码
#import <Foundation/Foundation.h>
#pragma mark 类
#import "Person.h"
#pragma mark - main函数
int main(int argc, const char * argv[])
{
#pragma 1.block中可以访问外面的变量
/*
int a = 10;
void (^myBlock)() = ^{
NSLog(@"a = %i",a);
};
myBlock();
*/
#pragma 2.block中可以定义和外界同名的变量, 并且如果在block定义了和外界同名的变量,在block中访问的是block中的变量
/*
int a = 10;
void (^myBlock)() = ^{
int a = 20;
NSLog(@"a = %i",a);
};
myBlock();
*/
#pragma 3.默认情况下,不可以在block中修改外界变量的值
// 因为block中的变量 和外界的变量 并不是同一个变量
// 如果block中 访问到了外界的变量,block会将外界的变量拷贝一份到 堆 内存中
// 因为 block中 使用外界变量是copy, 所以在调用之前修改外界变量的值,不会影响到block中copy的值
/*
int a = 10;
NSLog(@"%p",&a); // 0x7fff5fbff7bc
void (^myBlock)() = ^{
// a = 20; // varable is assginable(missing __block type specifier)
NSLog(@"a = %i",a); // 10
NSLog(@"%p",&a); // 0x103000160
};
a = 20;
myBlock();
*/
#pragma 4.不默认情况下,不可以在block中修改外界变量的值
// 如果想在block中修改外界变量的值,必须在外界变量 前面加上 __block
// 如果在block中修改了外界变量的值, 会影响到外界变量的值
/*
__block int a = 10;
NSLog(@"%p",&a);
void (^myBlock)() = ^{
a = 33;
NSLog(@"a = %i",a);
NSLog(@"%p",&a);
};
myBlock();
NSLog(@"a = %i",a);
*/
#pragma 5.为什么不加 __block 不能在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_c2811e_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; 如果没有添加 __block是值传递
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 };
// __main_block_impl_0 应该是一个结构体
// void (*myBlock)() = &__main_block_impl_0(__main_block_func_0, &__main_block_desc_0_DATA, a)) 其中a 是一个值传递
*/
#pragma code
/*
int a = 10;
void (^myBlock)() = ^{
// a = 10;
NSLog(@"a = %i",a);
};
myBlock();
*/
#pragma 6.为什么加 __block 就可在block中修改外界变量的值
/*
a = 10; 如果 加上 __block之后就是地址传递,就可在block中修改外界变量的值
void (*myBlock)() = &__main_block_impl_0(__main_block_func_0, &__main_block_desc_0_DATA, (__Block_byref_a_0 *)&a, 570425344));
*/
/*
__block int a = 10;
void (^myBlock)() = ^{
a = 13;
NSLog(@"a2 = %i",a);
};
NSLog(@"a1 = %i",a);
myBlock();
NSLog(@"a3 = %i",a);
*/
#pragma 7.面试 -- block是存储在堆中(copy情况下) 还是栈中(默认情况下)
// 默认情况下 block存储在栈中,如果对block进行copy操作,block会转移到堆中
// 如果block在堆中, block访问了外界的对象,那么会对外界的对象进行retain
// 如果在block 中访问了外界的对象,一定要给对象加上 __block, 只要加上了 __block 哪怕block在堆中,也不会对外界的兑现进行retain操作
// Person *p = [[Person alloc]init];
__block Person *p = [[Person alloc]init];
NSLog(@"retainCount = %lu",[p retainCount]);
void (^myBlock)() = ^{
NSLog(@"p = %@",p);
NSLog(@"retainCount = %lu",[p retainCount]);
};
Block_copy(myBlock);
myBlock();
[p release];
return 0;
}
Person
>>>.h
#import <Foundation/Foundation.h>
@interface Person : NSObject
@end
>>>.m
#import "Person.h"
@implementation Person
- (void)dealloc
{
NSLog(@"%s",__func__);
[super dealloc];
}
@end
一、获取cpp文件
通过-rewrite-objc指令
转成cpp文件
cpp文件代码