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

版权声明:本文为博主原创文章,转载请注明出处。 https://blog.csdn.net/u011619283/article/details/88564714

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。

猜你喜欢

转载自blog.csdn.net/u011619283/article/details/88564714