iOS block几种类型,为什么使用copy修饰

block快的存储位置(block入口的地址)可能存放在3个地方:代码区(全局区)、堆区、栈区(ARC情况下回自动拷贝到堆区、因此ARC下只有两个地方:代码区和堆区)
有三种常见的类型:
①<NSGlobalBlock: 0x102cef0b8>
存储在程序的代码段,全局区;NSGlobalBlock:不会访问任何外部变量,比如:

    void(^blockA)(void) = ^{
        NSLog(@"just a block");
    };
    NSLog(@"%@", blockA);

②<NSMallocBlock: 0x60000025b120>
存储在堆上。当blcok的引用计数为0时会被销毁,比如:

    int value = 10;
    void(^blockB)(void) = ^{
        NSLog(@"just a block === %d",value);
    };
    NSLog(@"%@", blockB);

③<NSStackBlock: 0x7ffeecf0fad0>
存储在栈上,NSStackBlock:在block内部引用外部变量,除了函数作用域会被销毁,引用导致奔溃,所以需要拷贝到堆上,比如:

    // 强行在ARC上将一个block创建在栈上
    void(^__weak blockC)(void) = ^{
        NSLog(@"just a block === %d",value);
    };
    NSLog(@"%@", blockC);

//注意:在arc情况下,没有NSStackBlock这个类型,如果有系统自动copy成为NSMallocBlock,同时会拷贝代码内部变量如:

    int base = 2;
    base += 2;
    long (^sums)(int,int)  = ^ long (int a,int b){
        return base + a + b;
    };
    base ++;
    NSLog(@"%ld",sums(1,2));
    //输出的结果为 7 arc下提前拷贝base

需要特别注意的是,在ARC下,很多都已经自动帮我们Copy成了MallocBlock了,由于Block是默认建立在栈上,所以如果离开方法作用域就会释放,如果要在外部调用,需要用copy指向它,这样就拷贝到了堆区,strong不具有拷贝功能

你可能感兴趣的:(iOS block几种类型,为什么使用copy修饰)