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是对象的验证的主要内容,如果未能解决你的问题,请参考以下文章

浅谈Objective-C中的block那些事

iOS的内存管理和引用计数规则Block的用法以及三种形式(stackmallocglobal)

iOS的内存管理和引用计数规则Block的用法以及三种形式(stackmallocglobal)

关于block以及__bridge的一些笔记

Kotlin 匿名扩展函数作为参数时的语义

iOS中block 静态全局局部变量block变量,以及对象,详解!