Block的三种类型
block有3中类型,可以通过 class方法或者 isa 指针查看具体类型,最终都是继承与NSBlock 的类型 有NSGlobalBlock,NSMallocBlock,NSStackBlock
这三种 block在内存中分配的位置是不同的
那么什么样的 block 是 NSGlobalBlock?什么样的 block 是 NSMallocBlock ?什么样的 block 是NSStackBlock ?
为了能够准确的研究B lock 内存分配 一下代码是在非ARC环境下测试
image.png如果 block 内部没有访问auto 变量 那么这个 block 就是 NSGlobalBlock 类型
int height = 10; ///全局变量
void testBlock() {
///globalBlock
void(^block1)(void) = ^ {
NSLog(@"hello world");
};
NSLog(@"%@",[block1 class]);
///MallocBlock
static int age = 10; ///静态变量
void(^block2)(void) = ^{
NSLog(@"age = %d",age);
};
NSLog(@"%@",[block2 class]);
///StackBlock
NSLog(@"%@",[^{
NSLog(@"height = %d",height);
} class]);
}
控制器输出打印结果
2019-02-22 10:11:20.325501+0800 Block01[18811:1127199] __NSGlobalBlock__
2019-02-22 10:11:20.325704+0800 Block01[18811:1127199] __NSGlobalBlock__
2019-02-22 10:11:20.325716+0800 Block01[18811:1127199] __NSGlobalBlock__
如果 block 内部访问了 auto 变量 那么这个 block 就是 NSStackBlock
int height = 10; ///全局变量
void testBlock() {
///__NSGlobalBlock__
void(^block1)(void) = ^ {
NSLog(@"hello world");
};
NSLog(@"%@",[block1 class]);
///__NSStackBlock__
int age = 10; //auto局部变量
void(^block2)(void) = ^{
NSLog(@"age = %d",age);
};
NSLog(@"%@",[block2 class]);
///__NSGlobalBlock__
NSLog(@"%@",[^{
NSLog(@"height = %d",height);
} class]);
}
控制器输出打印结果
2019-02-22 10:15:48.642882+0800 Block01[20101:1139963] __NSGlobalBlock__
2019-02-22 10:15:48.643117+0800 Block01[20101:1139963] __NSStackBlock__
2019-02-22 10:15:48.643135+0800 Block01[20101:1139963] __NSGlobalBlock__
我们平时使用 block 的时候 一般都有 copy 操作,这样做是为什么呢?
image.png2019-02-22 10:29:11.315472+0800 Block01[23997:1178680] NSStackBlock
block是分配在栈内存的 当函数作用域结束的时候 block 就会被内存回收,那么这个时候去调用 block 内部代码 ,这个时候 block 可能已经销毁了 它捕获的 string 变量也可能已经不存在了 这个时候输出 string 的值 就会造成坏内存访问.
image.png如何能够让 block 一直存在内存中呢 ?
调用[ block copy]就可以将 block 从栈内存拷贝到堆内存 ,在使用 block 的时候就不会出现 block 已经被销毁的情况.
void (^block)(void);
void testBlock() {
NSString *string = @"dzb";
block = [^{
NSLog(@"string = %@",string);
} copy];
NSLog(@"%@",[block class]);
}
///控制台输出结果
2019-02-22 10:33:54.178636+0800 Block01[25341:1191775] __NSMallocBlock__
2019-02-22 10:33:57.641726+0800 Block01[25341:1191775] string = dzb
下边的图可以总结出 block 的类型
image.png
在我们平时开发中 定义 block 的地方 和 调用 block 地方可能不在一个地方,这种情况下就需要将 block copy 保证 block 不被销毁
image.png2019-02-22 10:39:41.851458+0800 Block01[26979:1208502] NSMallocBlock
2019-02-22 10:39:41.851682+0800 Block01[26979:1208502] string = dzb
好了,我是大兵布莱恩特,欢迎加入博主技术交流群,iOS 开发交流群
QQ20180712-0.png