美文网首页
三种Block(三)

三种Block(三)

作者: 凉白开0072 | 来源:发表于2017-11-21 11:42 被阅读58次

    块的内部结构

    <<编写高质量代码的52个有效方法>>中摘抄如下:


    图一
    图二
    图三

    OC中的Block的三种类型

    OC中,一般Block就分为以下3种:

    1. _NSConcreteStackBlock
      特点:存放在栈区,生命周期由系统控制的,一旦返回之后,就被系统销毁了。
      栈block的表现形式:

      • 条件1:拥有局部变量(自动变量)或者成员属性变量(即使被strong或者copy修饰的成员变量)
      • 没有被强引用
      • 如下面的例1:
    2. _NSConcreteGlobalBlock
      特点:这种Block存储在程序的数据区域(跟函数存储在一起),生命周期从创建到应用程序结束。全局block的copy是个空操作,实际上就相当于单粒.
      全局block的表现形式:

      • block中没有用到任何block内部以外的变量
      • block内部仅仅用到了全局变量/静态全局变量,静态变量
      • 如下面的例2
    3. _NSConcreteMallocBlock:
      特点:存放在堆区,没有强指针引用即销毁,生命周期由程序员控制
      堆block的表现形式:
      堆中的block无法直接创建,其需要由_NSConcreteStackBlock类型的block拷贝而来(也就是说block需要执行copy之后才能存放到堆中)
      在ARC环境下,以下几种情况,编译器会自动的判断,把Block自动的从栈copy到堆

      • 手动调用copy的栈block
      • 栈Block被强引用,被赋值给__strong或者id类型
      • copy修饰的成员属性引用的block会被复制一份到堆中成为MallocBlock,这可以归纳为上一条
      • Block是函数的返回值
      • 调用系统API入参中含有usingBlcok的方法
      • 举例3:

    例1:stackBlock

    #import "TestObject.h"
    
    @interface TestObject ()
    {
        int b;
    }
    @property (nonatomic,copy) NSString *str;
    @end
    
    @implementation TestObject
    
    - (void)test {
        
        int i = 10;
        //注意,这个block可是srong类型,OC中定义一个变量默认情况下是__strong类型
        //堆block
        //        void (^block)() = ^{i;};
        //栈block
        __weak void (^weakBlock)() = ^{i;};
        // 创建时,都会在栈中
        NSLog(@"%@", ^{i;});
        // 获取了该对象的成员属性变量
        NSLog(@"%@", ^{b;});
        //被copy修饰的str
        NSLog(@"=====%@", ^{ _str;} );
        // 如果是weak类型的block
        NSLog(@"%@", weakBlock);
    }
    @end
    

    打印结果如下:

    <__NSStackBlock__: 0x7fff5b3600f0>
    <__NSStackBlock__: 0x7fff5b3600b8>
    <__NSStackBlock__: 0x7fff5b360118>
    =====<__NSStackBlock__: 0x7fff5594c0a8>
    

    例2:两种globalBlock

    #import <Foundation/Foundation.h>
    
    int global_i = 1;
    static int static_global_j = 2;
    
    int main(int argc, const char * argv[]) {
        
        static int static_k = 3;
        //globalBlock1:类型1
        void (^myBlock)(void) = ^{
            NSLog(@"Block中 变量 = %d %d %d",static_global_j ,static_k, global_i);
        };
        myBlock();
        NSLog(@"myBlock===%@",myBlock);
        
        //globalBlock2:类型2
        void (^block2)(void) = ^{
        
        };
        NSLog(@"block2===%@",block2);
        return 0;
    }
    
    

    打印结果:

    Block中 变量 = 2 3 1
    myBlock===<__NSGlobalBlock__: 0x10cc6b050>
    block2===<__NSGlobalBlock__: 0x10cc6b090>
    

    例3:堆block

    
    #import "TestObject.h"
    
    @interface TestObject ()
    {
        int b;
    }
    @property (nonatomic,copy) void (^tesblock)();
    @property (nonatomic,copy) NSString *str;
    @end
    @implementation TestObject
    - (void)test {
        int i = 10;
        // 1.手动调用copy的栈block
        NSLog(@"%@", [^{i;} copy]);
        //注意,这个block可是srong类型,OC中定义一个变量默认情况下是__strong类型
        //2.栈Block被强引用,被赋值给__strong或者id类型
        void (^block)() = ^{i;};
        NSLog(@"block===%@", block);
        //3.copy修饰的成员属性引用的block会被复制一份到堆中成为MallocBlock
        self.tesblock = ^{
            //如果没有这个i,那就是全局block,即使用copy引用,也是全局block,从而也说明全局block是不可囊转化成堆block
            i;
        };
         NSLog(@"tesblock===%@", self.tesblock);
        //4.Block是函数的返回值
        NSLog(@"block3===%@", [self test3]);
        //5.调用系统API入参中含有usingBlcok的方法(这个还不懂,以后有空在怼吧)
    }
    - (void(^)())test3 {
        //如果是全局block那么,即使是函数的返回值,他仍然还是全局block
        //return ^{};
        int a;
        return ^{a;};
    }
    
    @end
    

    打印结果:

    <__NSMallocBlock__: 0x6000002425b0>
    block===<__NSMallocBlock__: 0x60400025c1a0>
    tesblock===<__NSMallocBlock__: 0x60400025c290>
    block3===<__NSMallocBlock__: 0x60400025c3b0>
    

    block作为函数的参数

    当Block为函数参数的时候,需要我们手动copy一份到堆上

    - (void)test {
        int i = 10;
        [self test4:^{i;}];
    }
    - (void)test4:(void (^)())sblock {
        //sblock是一个栈block,需要copy操作
         NSLog(@"sblock===%@", [sblock copy]);
    }
    

    相关文章

      网友评论

          本文标题:三种Block(三)

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