block概念

block的实质:

block实质是oc对闭包的对象实现,简单点来说 block就算是对象。

block的书写方式:
    //block 的一般形式
    int(^myBlock)(int) = ^(int count) {
        return count + 1;
    };
    //可以使用typedef定义相同类型的block
    typedef int (^commentBlock)(int);
    commentBlock blc = ^(int abc) {
        return abc;
    };

Block可以截获局部变量。
修改Block外部的局部变量,Block内部被截获的局部变量不受影响。
修改Block内部到局部变量,编译不通过。

typedef void (^myBlock)(void);
int a = 10;
int b = 20;
myBlock blk = ^(void) {
    NSLog(@"a = %d   b = %d", a, b);
};
blk();
a+= 10;
b+= 10;
blk();

通过打印得知两次打印结果一样,block内部可以截获局部变量,是另外一份,不再受原来的变量影响。

局部变量在block内部不是指针传递,而是值传递。所以外部的值改变不会影响内部的值。

想要可以修改局部变量,有两种方法

1.改变存储于特殊存储区域的变量。
全局变量、静态变量和静态全局变量都可以在block内部直接修改。

2.通过__block修饰符来改变。
__block说明符用于指定将变量值设置到哪个存储区域中,也就是说,当自动变量加上__block说明符之后,会改变这个自动变量的存储区域。

三种block

1.全局block、
在全局区域生成的全局block。
存储在程序的数据区域。
copy之后无变化。

2.栈block
正常的方法中生成的block。
存储在栈上,copy之后存储在堆上。

3.堆block
栈block copy到堆之后就生成了堆block。
存储在堆上,copy之后引用计数增加。

大部分block创建之后会自动copy到堆上。
在block被copy到堆上的时候,block通过__block持有的变量也一块被copy进去。等到block被废弃,没有block持有该变量的时候,变量自动释放。

block循环引用

如果在Block内部使用__strong修饰符的对象类型的自动变量,那么当Block从栈复制到堆的时候,该对象就会被Block所持有。
所以如果这个对象还同时持有Block的话,就容易发生循环引用。

最常见的情况就是控制器self创建了一个block变量,控制器self持有该block。同时如果该block内部引用self,此时就形成了相互持有死循环。

你可能感兴趣的:(block概念)