Block的总结

31 篇文章 1 订阅

总结

block的本质就是Objective-C对象,block的调用就是函数指针的调用

  1. block的本质是一个封装了函数调用以及函数调用环境的OC对象;
  2. block截获自动变量值的规则:
    1. 局部变量会被直接截获;
    2. 局部静态变量会被截获其指针;
    3. 全局变量并不会被截获,而是直接使用;
  3. block截获对象的规则:
    1. block位于栈上,则不会对截获的对象变量进行强引用;
    2. block从栈上复制到堆上,调用copy函数,对截获的变量进行强/弱引用;
    3. block从堆上移除,调用dispose函数,自动释放引用的变量;
  4. block使用copy属性的原因:在MRC下,访问了自动变量的block处于栈上,容易被释放,使用copy可以将其复制到堆上,放在堆上便可以自己去控制Block的生命周期;在ARC下,对Block做了优化;
  5. block的循环引用:一个对象持有了这个Block,而在Block内部又使用了这个对象,就会造成循环引用;
  6. __block的作用:解决block内部无法修改自动变量值的问题;
  7. __block的注意点:不能修饰全局变量和静态变量;
  8. __block的实质:编译器将__block变量包装成一个对象,将截获到的值存在这个对象中,通过对截获的值进行赋值而更改原有的值;
  9. __forwarding指针的作用:可以实现无论__block变量配置在栈上还是堆上都能够正确地访问__block变量;


 

block有如下三种类型:

__NSGlobalBlock __ ( _NSConcreteGlobalBlock )

__NSStackBlock __ ( _NSConcreteStackBlock )

__NSMallocBlock __ ( _NSConcreteMallocBlock )

block在MRC和ARC环境下分别出现这三种类型的情况

MRC环境:

__NSGlobalBlock:没有访问外部auto变量,如果访问了外部static或者全局变量也是这种类型

void (^myBlock)(void) = ^{

        NSLog(@"this is a __NSGlobalBlock__");

    };

    NSLog(@"%@",[myBlock class]);

__NSStackBlock:访问了外部auto变量

int age = 30;

    void (^myBlock)(void) = ^{

        NSLog(@"this is a __NSStackBlock__%d",age);

    };

    NSLog(@"this is a %@",[myBlock class]);

__NSMallocBlock:__NSStackBlock类型调用了copy方法

int age = 30;

    void (^myBlock)(void) = [^{

        NSLog(@"this is a __NSMallocBlock__%d",age);

    } copy];

    NSLog(@"this is a %@",[myBlock class]);

 

上面就是MRC环境下的三种类型,如果对__NSGlobalBlock和__NSMallocBlock分别调用copy会是什么情况呢?

__NSGlobalBlock调用copy还是__NSGlobalBlock类型,__NSMallocBlock调用copy则引用计数+1

 

 

再看下ARC环境下的三种类型:

__NSGlobalBlock:和MRC环境一样,不再累赘

__NSStackBlock:访问了外部变量,但没有强引用指向这个block,而是直接打印出来

int age = 30;

     ;

    NSLog(@"this is a %@",[^{

        NSLog(@"this is a __NSStackBlock__%d",age);

    } class]);

__NSMallocBlock:ARC环境下只要访问了外部auto变量并且有强引用指向该block(或者作为函数返回值)就会自动将__NSStackBlock类型copy到堆上

这些情况有:

  • block作为函数返回值的时候;
  • block赋值给strong指针的时候;(arc下默认都是__strong修饰,所以下面的block赋值给了一个强引用指针)
  • block作为Cocoa API中方法名含有usingBlock的方法参数的时候;
  • block作为GCD API的参数的时候;

int age = 30;

    void (^myBlock)(void) = ^{

        NSLog(@"this is a __NSMallocBlock__%d",age);

    };

    NSLog(@"this is a %@",[myBlock class]);

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值