block原理学习(3.block的分类)

  • block是一个对象,调用block的父类最终都继承自NSObject.
// __NSGlobalBlock__ : __NSGlobalBlock : NSBlock : NSObject
    void (^block)(void) = ^{
        NSLog(@"Hello");
    };
    
    NSLog(@"%@", [block class]);
    NSLog(@"%@", [[block class] superclass]);
    NSLog(@"%@", [[[block class] superclass] superclass]);
    NSLog(@"%@", [[[[block class] superclass] superclass] superclass]);
  • block有三种类型,可以通过调用class方法或者isa指针查看具体类型,定义三个block:
		void (^block1)(void) = ^{
            NSLog(@"Hello");
        };
        
        int age = 10;
        void (^block2)(void) = ^{
            NSLog(@"Hello - %d", age);
        };
        
        NSLog(@"%@ %@ %@", [block1 class], [block2 class], [^{
            NSLog(@"%d", age);
        } class]);

打印结果:__NSGlobalBlock__ __NSMallocBlock__ __NSStackBlock__对应的就是block的三种类型。并且三种类型分别在内存的不同位置,如图:在这里插入图片描述内存是从上到下增长的

  • .text区域是代码段,平时定义的所有的类都在这个区域。
  • .data全局变量之类的包括static定义的局部变量。__NSGlobalBlock__类型的block就在这个区域,不常用。
  • 堆段是需要程序员自己申请管理内存,也就是alloc、free之类的。__NSMallocBlock__类型再这个区域
  • 栈段一般放的局部变量,特点是自动释放内存,如果局部变量所在的作用域结束了,就自动销毁了。__NSStackBlock__在栈这个区域
    那么block类型是怎么判断的呢?
    1、__NSGlobalBlock__类型的block是没有访问auto变量。
    2、__NSStackBlock__类型的block一般类型是访问了auto变量(mrc情况下,因为arc已经自动管理了内存),这种类型的block是在栈段,如果block所在的函数调用完,这个block就会销毁,当其他地方调用这种类型的block时候访问就会有问题。
    3、__NSMallocBlock__类型的block是拿到__NSStackBlock__进行拷贝之后返回之后就是这种类型的block。总结如下:
    在这里插入图片描述那么__NSGlobalBlock__跟__NSMallocBlock__拷贝之后呢?
    如果__NSGlobalBlock__拷贝之后还是__NSGlobalBlock__类型的。而__NSMallocBlock__类型的block拷贝之后引用计数器增加,类型不会改变。总结如图:在这里插入图片描述以上是mrc情况下,但在实际开放情况下用的都是arc,在arc情况下, 编译器会根据情况自动将栈上的block复制到堆上,比如:
    a、block作为返回值的时候。
    b、将block赋值给__strong指针时。
    c、block作为Cocoa API中方法名含有usingBlock的方法参数时。
    d、block作为GCD API参数时。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值