Block运行时的类型以及Block是对象的验证
Posted Haley_Wong
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Block运行时的类型以及Block是对象的验证相关的知识,希望对你有一定的参考价值。
Block运行时的类型
在用Clang命令,将block相关源代码转换为C++源码代码后。
可以看到函数内的原始Block的isa 都是_NSConcreteStackBlock
,但是其实际的类型会在运行时,根据实际情况变更和转换。
这里用源码测试Block在实际运行场景下的类型。
这里先针对函数内的block类型做一下总结:
- 1.如果block内部没有截获任何变量,则该Block就是全局类型。
- 2.如果Block内有截获变量且赋值给strong变量或者strong变量的属性,则该Block是Malloc类型。
- 3.如果Block没有任何strong变量持有,或者strong变量的属性持有,则该Block是Stack类型。
怎么验证Block是对象?
最近跟同事讨论NSObject中的isa指针,以及objc_object、objc_class等结构时,顺便利用runtime的一些api做了一些验证。
我们都知道对于对象,我们可以通过[obj class]、[obj superclass]、[[obj superclass] superclass] … 这样来获取对象的类、父类、父类的父类等。
突然想到我们之前block也是对象,那block能不能调用这些api呢?
我们也对block调用这些函数试试:
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
int main(int argc, const char * argv[])
@autoreleasepool
// insert code here...
NSLog(@"Hello, World!");
void (^block)(void) = ^
printf("block---1");
;
NSLog(@"block--class:%@", [block class]);
NSLog(@"block--superclass:%@", [block superclass]);
NSLog(@"block--superclass-superclass:%@", [[block superclass] superclass]);
NSLog(@"block--superclass-superclass-superclass:%@", [[[block superclass] superclass] superclass]);
block();
NSLog(@"=================================================");
int a = 10;
void (^mallocBlock)(void) = ^
printf("block---%d", a);
;
NSLog(@"mallocBlock--class:%@", [mallocBlock class]);
NSLog(@"mallocBlock--superclass:%@", [mallocBlock superclass]);
NSLog(@"mallocBlock--superclass-superclass:%@", [[mallocBlock superclass] superclass]);
NSLog(@"mallocBlock--superclass-superclass-superclass:%@", [[[mallocBlock superclass] superclass] superclass]);
mallocBlock();
NSLog(@"=================================================");
// 3. 直接调用的block的class
NSLog(@"stackBlock--class:%@", [^ NSLog(@"%d",a); class]);
NSLog(@"stackBlock--superclass:%@", [^ NSLog(@"%d",a); superclass]);
NSLog(@"stackBlock--superclass-superclass%@", [[^ NSLog(@"%d",a); superclass] superclass]);
NSLog(@"stackBlock--superclass-superclass-superclass%@", [[[^ NSLog(@"%d",a); superclass] superclass] superclass]);
return 0;
打印结果如下:
2019-03-15 00:03:39.299381+0800 TestBlock[24826:801310] Hello, World!
2019-03-15 00:03:39.299716+0800 TestBlock[24826:801310] block--class:__NSGlobalBlock__
2019-03-15 00:03:39.299750+0800 TestBlock[24826:801310] block--superclass:__NSGlobalBlock
2019-03-15 00:03:39.299776+0800 TestBlock[24826:801310] block--superclass-superclass:NSBlock
2019-03-15 00:03:39.299801+0800 TestBlock[24826:801310] block--superclass-superclass-superclass:NSObject
block---12019-03-15 00:03:39.299832+0800 TestBlock[24826:801310] =================================================
2019-03-15 00:03:39.299858+0800 TestBlock[24826:801310] mallocBlock--class:__NSMallocBlock__
2019-03-15 00:03:39.299881+0800 TestBlock[24826:801310] mallocBlock--superclass:__NSMallocBlock
2019-03-15 00:03:39.299898+0800 TestBlock[24826:801310] mallocBlock--superclass-superclass:NSBlock
2019-03-15 00:03:39.299914+0800 TestBlock[24826:801310] mallocBlock--superclass-superclass-superclass:NSObject
block---102019-03-15 00:03:39.299934+0800 TestBlock[24826:801310] =================================================
2019-03-15 00:03:39.299957+0800 TestBlock[24826:801310] stackBlock--class:__NSStackBlock__
2019-03-15 00:03:39.300095+0800 TestBlock[24826:801310] stackBlock--superclass:__NSStackBlock
2019-03-15 00:03:39.300122+0800 TestBlock[24826:801310] stackBlock--superclass-superclass:NSBlock
2019-03-15 00:03:39.300137+0800 TestBlock[24826:801310] stackBlock--superclass-superclass-superclass:NSObject
是不是很神奇,block的Class的超类是NSObject。
以上是关于Block运行时的类型以及Block是对象的验证的主要内容,如果未能解决你的问题,请参考以下文章
iOS的内存管理和引用计数规则Block的用法以及三种形式(stackmallocglobal)