Block的三个类型:
1._NSConcreteGlobalBlock,全局的静态block,不会访问外部的变量。就是说如果你的block没有调用其他的外部变量,那你的block类型就是这种。
2._NSConcreteMallocBlock 保存在堆中的 block,当引用计数为 0 时会被销毁。
3._NSConcreteStackBlock 保存在栈中的 block,当函数返回时会被销毁。
如果是全局静态block的话,他直到程序结束的时候,才会被被释放。但是我们实际操作中基本上不会使用到不访问外部变量的block。
如果是保存在栈中的block,他会随着函数调用结束被销毁。从而导致我们在执行一个包含block的函数之后,就无法再访问这个block。因为(函数结束,函数栈就销毁了,存在函数里面的block也就没有了),我们再使用block时,就会产生空指针异常。
如果是堆中的block,也就是copy修饰的block。他的生命 周期就是随着对象的销毁而结束的。只要对象不销毁,我们就可以调用的到在堆中的block。
#import "ViewController.h"
@interface ViewController ()
@property (nonatomic, copy) void(^myblock)();
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//1 __NSGlobalBlock__ 全局block 存储在代码区(存储方法或者函数)
void(^myBlock1)() = ^() {
};
NSLog(@"%@",myBlock1);
//2 __NSStackBlock__ 栈block 存储在栈区
//block内部访问外部变量
//block的本质是一个结构体
int n = 5;
void(^myBlock2)() = ^() {
};
NSLog(@"%@", myBlock2);
//3 __NSMallocBlock__ 堆block 存储在堆区 对栈block做一次copy操作
void(^myBlock3)() = ^() {
};
NSLog(@"%@", [myBlock3 copy]);
/*
由以上三个例子可以看出当block没有访问外界的变量时,是存储在代码区,
当block访问外界变量时时存储在栈区, 而此时的block出了作用域就会被释放
以下示例:
*/
[self test];//当此代码结束时,test函数中的所有存储在栈区的变量都会被系统释放, 因此如果属性的block是用assign修饰时 当再次访问时就会出现野指针访问.
self.myblock();
}
- (void)test {
int n = 5;
[self setMyblock:^{
NSLog(@"%d",n);
}];
NSLog(@"test--%@",self.myblock);
}
@end