Block有3种类型,可以通过调用class方法或者isa指针查看具体类型,最终都是继承自NSBlock类型
- NSGlobalBlock ( _NSConcreteGlobalBlock )
- NSStackBlock ( _NSConcreteStackBlock )
- NSMallocBlock ( _NSConcreteMallocBlock )
一.Block对象的存储区域
Block的类型 | 对象的存储域 |
---|---|
NSGlobalBlock | 程序的数据区域(.data) |
NSStackBlock | 栈 |
NSMallocBlock | 堆 |
二.判断Block的类型
Block的类型 | 环境 |
---|---|
NSGlobalBlock | 没有访问auto变量 |
NSStackBlock | 访问了auto变量 |
NSMallocBlock | NSStackBlock调用了copy |
三.Block调用copy操作
Block的类型 | 对象的存储域 | 复制效果 |
---|---|---|
NSGlobalBlock | 程序的数据区域 | 什么也不做 |
NSStackBlock | 栈 | 从栈复制到堆 |
NSMallocBlock | 堆 | 引用计数增加 |
四.ARC环境下自动为Block进行copy操作的情况
1.block作为函数返回值时
typedef void(^Block)(void);
Block test() {
int age = 10;
return ^{
NSLog(@"age=%d", age);
};
}
int main(int argc, char * argv[]) {
@autoreleasepool {
Block block = test();
block();
return 0;
}
}
2.将block赋值给__strong指针时
void (^block)(void);
void test() {
int age = 10;
block = ^{
NSLog(@"age=%d", age);
};
}
int main(int argc, char * argv[]) {
@autoreleasepool {
test();
block();
return 0;
}
}
3.block作为Cocoa API中方法名含有usingBlock的方法参数时
NSArray *array = [[NSArray alloc] init];
[array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSLog(@"%d", idx);
}];
4.block作为GCD API的方法参数时
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"1111");
});
网友评论