Block基础

一个最基本的block

void (^block)(void) = ^(void){
    NSLog(@"这是一个无参数无返回值的block");
};
block();//block的灵活性
这边有个思考,如上的block是在储存的哪个区域?

如果没有深究,凭经验可以说它存在常量区或栈区,因为当前block只是临时变量。
实际上block存在堆区,因为在当前的ARC环境下,block一旦定义出来,编译器就会自动把栈上的block copy到堆里面。
这边再思考一下,block是用什么修饰呢?你可能说copy,那strong是否可以呢?其实strong也是可以的,在当前的arc下,其实已经没有什么区别。

block的分类

首先了解一下几个存储区域:
  • 代码段:写的代码都存在这边
  • 数据区(常量区):存放全局变量,NSGlobalBlock存放在这边
  • 栈区:存放局部变量,不需要程序员管理,系统自动分配,自动销毁,NSStackBlock存放在这
  • 堆区:存放我们自己alloc出来的对象,动态分配内存,需要程序员自己申请内存,自己管理,NSMallocBlock存放在这
// -| NSGlobalBlock
// 没有引用auto变量
void (^block)(void) = ^(void){
    NSLog(@"没有引用auto变量");
}
NSLog(@"%@",block); //这边用%@ --> block是一个对象
// -| NSStackBlock 
// 这边需要MRC环境
// 访问了auto变量
int a = 10; // -->栈区
void (^block)(void) = ^(void){
    NSLog(@"访问了auto变量 %d",a);
}
NSLog(@"%@",block);
// -| NSMallocBlock 
// ARC环境Xcode帮我们处理成了堆block 
// 防止出现释放了还去访问导致野指针crash
int a = 10; // -->栈区
void (^block)(void) = ^(void){
    NSLog(@"ARC环境 访问了auto变量 %d",a);
}
NSLog(@"%@",block);
总结:
Block类型 环境 内存 拷贝
NSGlobalBlock 没有访问auto变量 数据区 什么也不做
NSStackBlock 访问auto变量 从栈复制到堆
NSMallocBlock NSStackBlock调用了copy 引用计数增加

在ARC环境下,编译器会自动将栈上的block copy到堆上

block的使用——链式编程

block当作函数的返回值
- (void)viewDidLoad 
{
    self.getSomeString(@"后被处理");
}
- (void(^)(NSString *))getSomeString
{
    void(^block)(NSString *) = ^(NSString *sting){
        NSLog(@"这边进行一系列处理 %@",sting);
    };
    NSLog(@"这边会被先调用");
    return block;
}
block当作函数的参数

异步性:比如AFN的successBlock和failBlock

- (void)viewDidLoad 
{
    [self request:^(NSString *string) {
        NSLog(@"%@",string);
    }];
}
- (void)request:(void(^)(NSString* string))block
{
    block(@"异步处理一些问题");
}
block当作一个参数

灵活性:保存一段代码块,在任何想用的地方去调用实现

block的变量截获
1、局部变量截获,是值的截获
int num = 10;
void(^block)(void) = ^(void){
    NSLog(@"num = %d",num);
};
num = 20;
block();

这里num的打印值为10,原因就是对局部变量的截获是值截获。

NSMutableArray *arr = [NSMutableArray arrayWithObjects:@"1",@"2",nil];
void(^block)(void) = ^(void){
    NSLog(@"%@",arr);
    [arr addObject:@"4"];
};
[arr addObject:@"3"];
arr = nil;
block();

这里的打印为1,2,3,局部对象变量的截获也是一样,是截获的值,而不是指针,在外部将其置nil也对block没有影响,但是对象调用方法会影响

2、局部静态变量截获,是指针截获
static int num = 10;
void(^block)(void) = ^(void){
    NSLog(@"num = %d",num);
};
num = 20;
block();

这里num的打印值为20,意味着num = 20修改有效的,即是指针截获,同样,在block里去修改变量num也是有效的。

3、全局变量,静态全局变量block是不截获的,直接进行访问

具体的可以通过通过命令clang -rewrite-objc xxx.m生成.cpp文件,或者通过xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc -fobjc-arc -fobjc-runtime=ios-9.0.0 XX.m.m文件转成 .cpp文件,查看c++的代码。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • block本质上是封装了函数调用以及函数调用环境的OC对象,为什么这么说呢?我们可以从底层数据结构来看.下面是创建...
    夜沐月阅读 3,607评论 0 0
  • Block基础和retain cycle(循环引用) blcok简介 Block 是c语言的扩展,并不是什么高新技...
    董军1990阅读 14,209评论 22 69
  • 目录一,本质二,变量捕获三,类型四,对象类型的auto变量 一,本质 1,实例代码 2,底层代码(用clang进行...
    码小菜阅读 1,778评论 0 3
  • block块是在ios4开始,就出现了。block实质就是C语言的回调函数。block函数定义如下 void (^...
    zl520k阅读 1,580评论 0 0
  • 在iOS 4.0之后,block横空出世,它本身封装了一段代码并将这段代码当做变量,通过block()的方式进行回...
    Clark_new阅读 3,395评论 0 4

友情链接更多精彩内容