全局块、栈块、堆块

void (^block) ();
    int a;
    if (1 == a) {
        block = ^{
            NSLog(@"1");
        };
    } else {
        block = ^{
            NSLog(@"others");
        };
    }
    block();

定义在ifelse语句中的2block都会被分配到栈内存中。编译器会给每个block分配好栈内存,然而等离开相应的作用域后,编译器有可能会把分配给block的栈内存覆写掉。因此,上面的block只能保证其在ifelse语句作用域内有效,出了作用域有crash的可能。

解决办法:给块对象发送copy消息,如此就把块从栈拷贝到堆上了。拷贝后,块可以在定义的作用域外使用。一旦拷贝到堆上后,块就变成了带引用计数的对象了。后续的copy的操作都不会真的执行copy,只会增加块对象的引用计数。当块的对象的引用计数为0时,分配在块上的对象会像其他对象一样被系统回收。然而分配在栈内存的块,栈内存会被系统自动回收。所以以上代码是不安全的。使用copy之后,就不会出现crash问题了。

void (^testBlock) ();
    int b;
    if (1 == b) {
        testBlock = [^{
            NSLog(@"1");
        } copy];
    } else {
        testBlock = [^{
            NSLog(@"others");
        } copy];
    }

块可以分配在栈或堆上,也可以是全局的。分配在栈上的块可以拷贝到堆里,这样子,就可以和标准的OC对象一样,具有引用计数了!

查阅资料:Effective Objective-C 2.0  编写高质量iOS与OS X代码的52个有效方法

 

 

 

原文地址:https://www.cnblogs.com/xiu619544553/p/5681248.html