ARC中的block

三大类型

NSGlobalBlock: 位于内存静态全局区。没有调用任何变量或者调用的为全局变量、静态变量。你可以理解为声明的时候,加了static关键字

static NSString *test = @"test";
//前面可加static修辞
dispatch_block_t block = ^{
    NSString *t = test;
};
NSLog(@"%@", block);
NSLog(@"%@", ^{
    NSString *t = test;
});

注意:这里打印分为通过变量赋值打印和直接打印,NSGlobalBlock是没有区别的,为何会区分,后面NSMallocBlock会说。

你可以在dispatch_block_t前也加上static关键字,表明类型,是静态全局的block,即NSGlobalBlock,不会有任何问题

NSStackBlock:内部引用的为非全局、静态区的变量,初始则为NSStackBlock

NSString *test = @"test";
NSLog(@"%@", ^{
    NSString *t = test;
});

注意:这里并不是采用通过一个变量赋值block再打印该变量的方式来确认类型,而是直接打印,区别在NSMallocBlock会提到
这里可以理解为

 ^{
    NSString *t = test;
 }

它其实就是一个局部变量,可以看做整个就是一个比如变量b,而局部变量是在栈中,因此打印出的类型是NSStackBlock

NSMallocBlock:由NSStackBlock类型的block通过copy后拷贝到堆中的block

NSString *test = @"test";
dispatch_block_t b = ^{
    NSString *t = test;
};
NSLog(@"%@", b);
NSLog(@"%@", [^{
    NSString *t = test;
} copy]);

block初始非NSGlobalBlock即NSStackBlock,只有经过copy后才会变为NSMallocBlock,上述代码中:

dispatch_block_t b = ^{
    NSString *t = test;
};

这里的变量b并不是初始化,右边才是,block作为oc对象,内部经过了优化,可以理解为它在等号右边的时候,若block类型为NSStackBlock,左边的变量赋值时会copy该block到堆,上述代码中,右边的

    ^{NSString *t = test}

作为局部变量,为NSStackBlock,左边的b在本次赋值的时候copy了右边的block到堆,成为NSMallocBlock

这里在dispatch_block_t前面加上static,你会发现会报错:

Error:(28, 33) initializer element is not a compile-time constant

加static,即表明你要申明的是一个静态的block类型,即NSGlobalBlock类型,而ARC优化后,变量通过等号赋值block,会将block拷贝到堆,变成NSMallocBlock,类型不符,自然会报错。

这个错误你通过类似

static UIView *model = [[UIView alloc] init];

一样能得到,我们知道,对象通过alloc分配地址在堆,因此不能用static修辞后直接赋值

小结

单纯的block,要么为NSGlobalBlock类型,要么为NSStackBlock类型

static NSString *global = @"global";
//NSGlobalBlock类型
^{
    NSString *g = global;
};

NSString *stack = @"stack";
//NSStackBlock类型
^{
    NSString *s = stack;
};

NSStackBlock类型的block通过等号赋值或者copy方法后,新的block为NSMallocBlock类型

NSString *stack = @"stack";
//NSMallocBlock类型
dispatch_block_t block = ^{
    NSString *s = stack;
};
//NSMallocBlock类型
[^{
    NSString *s = stack;
} copy];

3.ARC中,block作为属性,基于历史原因,平常还是用copy修辞,实际上属性内部自动生成的setter方法其实也是通过等号将传入的block赋值给成员变量,既然通过等号赋值,那么该变成NSStackBlock的自然会变,即:
block作为属性,可以不用copy而用strong修辞,甚至两者都可以省略

你可能感兴趣的:(ARC中的block)