美文网首页
iOS Block用法及原理

iOS Block用法及原理

作者: 黑夜中的星辰 | 来源:发表于2019-10-30 16:02 被阅读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指针访问变量,进而操作变量。

    相关文章

      网友评论

          本文标题:iOS Block用法及原理

          本文链接:https://www.haomeiwen.com/subject/baoovctx.html