欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Block运行时的类型以及Block是对象的验证

程序员文章站 2024-02-29 23:48:46
...

Block运行时的类型

在用Clang命令,将block相关源代码转换为C++源码代码后。
可以看到函数内的原始Block的isa 都是_NSConcreteStackBlock,但是其实际的类型会在运行时,根据实际情况变更和转换。

这里用源码测试Block在实际运行场景下的类型。
Block运行时的类型以及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。