iOS开发 Block
2021-01-11 本文已影响0人
喜剧收尾_XWX
一、block分类
block是一中特殊的oc对象,主要分为以下3类
- __NSGlobalBlock :没有访问外部auto自动变量,如果访问了全局静态变量
static_global
、局部静态变量static
或者全局变量也是这种类型。且能改变全局变量的值。
static NSString *indexString = @"xingweixin";
extern NSString *myExternString;
extern NSString *myExternString2;
self.block = ^{
//全局变量
myExternString2 = @"fengmengyue";
NSLog(@"_____%@",myExternString2);
NSLog(@"_____%@",indexString);
};
self.block();
NSLog(@"%@",[self.block class]); //__NSGlobalBlock
- __NSStackBlock
(1)在MRC下访问了外部auto变量,则属于栈区block
int index = 15;
void(^TestVCBlock)(void) = ^{
NSLog(@"----%d",index);
};
TestVCBlock();
NSLog(@"%@",[TestVCBlock class]); //__NSStackBlock
(2) 在ARC下访问了外部变量,但没有强引用指向这个block
int index = 15;
NSLog(@"%@",[^{
NSLog(@"----%d",index);
} class]);
- __NSMallocBlock
(1)在MRC下,用copy修饰__NSStackBlock后则为__NSMallocBlock
void(^TestVCBlock)(void) = [^{
NSLog(@"----%d",index);
} copy];
TestVCBlock();
NSLog(@"%@",[TestVCBlock class]);
(2)在ARC下,ARC环境下只要访问了外部auto变量而且有强引用指向该block(或者作为函数返回值)就会自动将__NSStackBlock类型copy到堆上
void(^TestVCBlock)(void) = ^{
NSLog(@"----%d",index);
} ;
TestVCBlock();
NSLog(@"%@",[TestVCBlock class]);
二、block特性
1.捕获自动变量
(1) 自动变量是什么时候被block捕获进去的?为什么值不能修改?
- block捕获自动变量是捕获block体中用到的局部变量,用不到的不去捕获
- 自动变量val虽然被捕获进来了,但是是用 __cself->val来访问的。Block仅仅捕获了val的值,并没有捕获val的内存地址。所以在__main_block_func_0这个函数中即使我们重写这个自动变量val的值,依旧没法去改变Block外面自动变量val的值。
(2) 全局变量和静态全局变量值在block为什么能更改,局部静态变量的值为什么能更改?
- 全局变量global_i和静态全局变量static_global_j的值增加,以及它们被Block捕获进去,这一点很好理解,因为是全局的,作用域很广,所以Block捕获了它们进去之后,在Block里面进行++操作,Block结束之后,它们的值依旧可以得以保存下来。
- 静态变量传递给Block是内存地址值,所以能在Block里面直接改变值。
(3)如何修改自动变量中的值
- 传递内存地址到Block中,改变变量的值。
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
NSMutableString * str = [[NSMutableString alloc]initWithString:@"Hello,"];
void (^myBlock)(void) = ^{
[str appendString:@"World!"];
NSLog(@"Block中 str = %@",str);
};
NSLog(@"Block外 str = %@",str);
myBlock();
return 0;
}
- 使用__block修饰局部变量