iOS Block用法及原理

2019-10-30  本文已影响0人  黑夜中的星辰

//Block语法

//^返回值类型(参数列表){表达式}

- (void)some{

    ^int(int count){

        return count + 1;

    };

    //返回值类型可省略

    ^(int count){

        return count + 1;

    };

    //参数列表为空,可省略

    ^{

        return @"123";

    };

    //最简洁的语法:^{};

}

- (block)someActionTwo:(block)block{

    return^(inti){

        block(2);

        returni +1;

    };

}

blockblockt =  [selfsomeActionTwo:^int(inti) {

        NSLog(@"##########i");

        returni;

    }];

block的用法

1.block作为参数

[selfsomeAction:^int(inti) {

        NSLog(@"i");

        returni ++;

    }];

- (void)someAction:(int(^)(inti))block{

    block(2);

}

2.block作为属性变量

//Block类型变量 语法:返回值类型(^变量名)(参数列表)

@property(nonatomic,copy)NSString *(^Block)(NSString *strone);

//借助typedef可简写typedef int(^block)(int);

block的分类

block分为栈block:_NSConcreteStackBlock,堆block:_NSConcreteMallocBlock,全局block:_NSConcreteGlobalBlock

栈block:block最初是在栈上创建的,只用到局部变量,没有被强指针指向的block是栈block;

堆block:在ARC中,系统会视情况而定(一旦block被赋值就会被copy到堆上),将栈上的block,copy到堆上,这是因为栈上的内存是有系统控制的,栈block出了作用域就会被销毁,为了延长block的生命周期,将其copy到堆上

全局block:生命周期从创建开始到程序结束,相当于单例的存在,它不会用到临时变量,只会用到全局或静态变量或者没有用到变量

block对外界变量的捕获

block可以捕获任何外界变量,捕获到之后会将其作为自身结构体的成员变量,其中局部变量,静态变量会被追加到block结构体的构造函数中,从clang翻译的源码中可以看到:

void (*Block)(void) = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, &static_k, val));

block的构造函数追加了局部变量的值,和静态变量的地址

 static int j = 10;

    inti =10;

  void(^block)(void) =  ^{

        NSLog(@"打印i:%dj:%d",i,j);

    };

    i++;

    j++;

    block();

打印结果为i:10,而不是11,因为block只捕获了局部变量的值,没有捕获地址,block内部会用到什么,在它创建的时候就会去捕获什么,这时候捕获到的也只能是值,为了防止局部变量之后被销毁,需要知道它的值的时候取不到了,所以是提前捕获,后续改变量的值在怎么变化,block取的都是最初捕获的值.  j:11,因为j是静态变量捕获了它的地址,所以可以实时获取j的值。

block内部修改外部变量

如果block内部直接修改外部变量,编译器会提示我们要加上__block ,为什么需要加上__block就可以修改了呢?

1.block捕获外界局部变量只是捕获了它的值,并没有捕获它的地址,对它只有只读能力,没有写的能力

2.被__block修饰之后,该变量会被转换为一个结构体:

struct __Block_byref_i_0 {

  void *__isa;

__Block_byref_i_0 *__forwarding;

int __flags;

int __size;

int i;

};

结构体中,它里面包含了isa,forwarding指针,flag标示,size大小,变量值,名字和变量名同名,在block的构造函数中 我们可以看到,追加了forwarding指针,block可以通过forwarding指针访问变量,进而操作变量。

上一篇下一篇

猜你喜欢

热点阅读