Block深入浅出

一:什么事Block

Block 是将函数及其执行上下文封装起来的对象。

基本使用:

@property(nonatomic, copy)void(^dismissBlock)(void);
@property(nonatomic, copy)void(^dismissBlock2)(UIView *view);
void (^logBlock)(NSString *)=^(NSString *paramStr){
};

在方法中生命

- (void)getMyBlock:(void(^)(int aa,int bb))myBlock;

typedef 返回类型(^block名)(参数类型 [参数名可选]);

typedef void(^MyBlock)(void);
 
@property(nonatomic, copy) MyBlock myBlock;

二:Block变量截获

1、局部变量截获 是值截获。 比如:

    NSInteger num = 3;
    NSInteger(^block)(NSInteger) = ^NSInteger(NSInteger n){
      return num *n;
    };
    num = 1;
    NSLog(@"%zd",block(2));

这里的输出是 6 而不是 2,原因就是对局部变量 num 的截获是值截获。 同样,在 block 里如果修改变量 num,也是无效的,甚至编译器会报错。

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

    };
    [arr addObject:@"3"];
    arr = nil;
    block();

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

2、局部静态变量截获 是指针截获。

    static NSInteger num = 3;
    NSInteger(^block)(NSInteger) = ^NSInteger(NSInteger n){
      return num *n;
    };
    num = 1;
    NSLog(@"%zd",block(2));

输出为 2,意味着 num = 1 这里的修改 num 值是有效的,即是指针截获。 同样,在 block 里去修改变量 m,也是有效的。

3、全局变量,静态全局变量截获:不截获,直接取值。

Block 的几种形式

  • 分为全局 Block(_NSConcreteGlobalBlock)、栈 Block(_NSConcreteStackBlock)、堆 Block(_NSConcreteMallocBlock)三种形式
  • 1、不使用外部变量的 block 是全局 block
  NSLog(@"%@",[^{
        NSLog(@"globalBlock");
    } class]);
  • 2、使用外部变量并且未进行 copy 操作的 block 是栈 block
NSInteger num = 10;
    NSLog(@"%@",[^{
        NSLog(@"%zd",num);
    } class]);

输出为stackBlock

__block底层实现原理

总结:加入了__block的表示后,栈中的指针地址永久的被copy到堆中了,不加入__block时候,只是在block内部时候会被暂时的从栈中被copy到堆中,等block结束后又回到栈中了,因为block对象布局中有copy方法,所以可以进行copy操作

  • __block可以用于解决block内部无法修改auto变量值的问题
  • __block不能修饰全局变量、静态变量(static)
  • 编译器会将__block变量包装成一个对象

你可能感兴趣的:(Block深入浅出)