美文网首页
Block结构分析

Block结构分析

作者: 简_爱SimpleLove | 来源:发表于2018-10-17 16:57 被阅读10次

将Xcode中文件转换为C++文件

第一步:打开终端,输入xcodebuild -showsdks 展示sdks,找到最新的模拟器型号:


image.png

第二步:cd到我们需要转换的文件所在的文件夹,注意只是cd到工程是不行的。
比如我们想要转换ViewController.m,必须要cd到这个文件夹才行,不然就提示找不到文件:


image.png
第三步:输入转换的命令即可,注意要把里面模拟器的型号和文件换成你自己的
转换成C++代码命令:xcrun -sdk iphonesimulator12.0 clang -rewrite-objc ViewController.m

包含weak类型数据转换成C++:xcrun -sdk iphonesimulator12.0 clang -S -rewrite-objc -fobjc-arc -fobjc-runtime=ios-12.0 BlockMemoryViewController.m

最后在你的文件夹下面就会多一个cpp文件。大功告成。

将OC中block转为C++代码

在.m文件中写多个不同的block,然后在按照上面的方法,转为C++的代码。.m文件如下:

#import "BlockStructureViewController.h"

typedef void(^eocblock)(void);
@interface BlockStructureViewController () {
    UILabel *label;
    eocblock instanceBlock;
}
@end

@implementation BlockStructureViewController

/**
 1、空的block
 2、包含简单类型(如int型)block
 3、包含临时的objc对象的block
 4、成员变量(objc)
 5、包含__block的变量
 6、global value
 7、全局static value
 8、局部static value
 */

//block结构:xcrun -sdk iphonesimulator12.0 clang -S -rewrite-objc -fobjc-arc -fobjc-runtime=ios-12.0 BlockStructureViewController.m

int globalValueOne = 10;
static int staticValue = 5;

- (void)viewDidLoad {
    
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor whiteColor];
    
}

- (void)emptyBlockFunction {
    
    void (^emptyBlock)(void) = ^{
        NSLog(@"八点钟学院");
    };
    emptyBlock();
}

- (void)simpleDataBlockFunction {
    
    int i = 10;
    void (^simpleDataBlock)(void) = ^{
        NSLog(@"八点钟学院 %d", i);
    };
    
    simpleDataBlock();
}

- (void)objcDataBlockFunction {
    UILabel *tmpLabel = [[UILabel alloc] init];
    void (^objcDataBlock)(void) = ^{
        NSLog(@"八点钟学院, %@", tmpLabel);
    };
    objcDataBlock();
}

- (void)classDataBlockFunction {
    void (^classDataBlock)(void) = ^{
        NSLog(@"八点钟学院 %@", label);
    };
    classDataBlock();
}

- (void)blockDataBlockFunction {
    
    __block int a = 100;  //a在栈里
    void (^blockDataBlock)(void) = ^{
        // block会将a存放在堆区(栈区的a指向堆区的a,堆区的a指向自己,所以实际上是同一个a)
        a = 1000; //在堆区修改a的值
        NSLog(@"八点钟学院, %d", a);
    };  //blockDataBlock 在堆区
    a = 10; //在栈区修改a的值
    blockDataBlock();
    NSLog(@"栈区a = %d", a);
}

- (void)globalDataBlockFunction {
    
    void (^globalDataBlock)(void) = ^{
        NSLog(@"八点钟学院 %d", globalValueOne);
    };
    globalDataBlock();
}

- (void)staticDataBlockFunction {
    
    void (^staticDataBlock)(void) = ^{
        NSLog(@"八点钟学院 %d", staticValue);
    };
    
    staticDataBlock();
}

- (void)tmpStaticDataBlockFunction {
    
    static int b = 11;
    instanceBlock = ^{
        b = 110;
        NSLog(@"八点钟学院 %d", b);
    };
    b= 100;
    instanceBlock();
}

@end

转化为C++代码,对比得到简化后的block的C++代码,如下:

#include "SJBlockCPlus.hpp"

// 全局变量
int thisGlobalValue = 1000;
// 全局静态变量
static int thisStaticValue = 10000;

struct block_impl {
    
    void *isa;
    int Flags;
    int Reserved;
    void *FuncPtr;
};

struct block_desc_0 {
    size_t reserved;
    size_t Block_size;
} __block_desc_0 = {0, sizeof(struct block_desc_0)};


struct block_impl_0 {
    
    struct block_impl impl;
    struct block_desc_0* Desc;
    
    /*这后面跟block的变量参数:
     int i;  // 普通变量
     UILabel *label; // 局部对象
     self // 如果是成员变量,需要传self,因为成员变量要通过self进行访问。比如 self->label
     */
    
    int *i;  // 这么只能放在结构体block_impl后面,不然会越界,内存顺序中加了一个i,访问不到block_impl
    
    // 构造函数 i(_i) 这是赋值i=_i的意思
    block_impl_0(void *fp, struct block_desc_0 *desc, int *_i, int flags=0):i(_i) {
        
        impl.Flags = flags;
        impl.FuncPtr = fp;
        Desc = desc;
    }
};


static void block_func_0(struct block_impl_0 *__cself) {
    
//    __cself->i = 100;
    //    printf("good My Love Ms Zhou == %d \n", __cself->i);

    // 传的地址所以修改要加*,打印也要加*转换
    *(__cself->i) = 100;
    printf("good My Love Ms Zhou == %d \n", *(__cself->i));

    
    // 因为作用域是全局的,所以全局变量和全局静态变量,可以直接访问
//    printf("good My Love Ms Zhou == %d \n", thisGlobalValue);
//    printf("good My Love Ms Zhou == %d \n", thisStaticValue);

}

void test() {
    
    // 局部静态变量传地址过去(因为地址是存在的,只是作用域和全局变量不一样)
    static int tmpStaticValue = 100000;
    struct block_impl_0 implTest = block_impl_0((void *)block_func_0, &__block_desc_0, &tmpStaticValue);

//    int i = 10;
//    struct block_impl_0 implTest = block_impl_0((void *)block_func_0, &__block_desc_0, i);
    void (*impTestPointer)() = (void (*)())&implTest;
    block_impl *tmpPointer = (block_impl *)impTestPointer;
    void (*Func)(block_impl *) = (void (*)(block_impl *))tmpPointer->FuncPtr;
    Func(tmpPointer);
    
//    printf("i = %d\n", i);
    
}

由上可知,block主要是由两个结构体(block_impl和block_impl_0)和一个执行函数(block_func_0)构成。一些需要传的变量加在结构体block_impl_0中。
总的结论:block你可以假想为一个class:变量(外部变量:成员变量,抓取的就是self,非成员变量抓取的就是这个非成员变量)、方法(执行函数)

注意点
修改的时候,要让存在栈区的变量和堆区的变量保持一致,所以在内部传的是地址过去,如下:

- (void)blockDataBlockFunction {
    
    //要让栈区和堆区保持一致,所以修改的时候是传的地址过去,block实现中,实际上是将a转化为了一个结构体
    
    __block int a = 100;  //a在栈里
    
    void (^blockDataBlock)(void) = ^{
        
        // block会将a存放在堆区(栈区的a指向堆区的a,堆区的a指向自己,所以实际上是同一个a)
        a = 1000; //在堆区修改a的值
        NSLog(@"八点钟学院, %d", a);
        
    };  //blockDataBlock 在堆区
    
    a = 10; //在栈区修改a的值
    blockDataBlock();
    NSLog(@"栈区a = %d", a);
}
image.png

两个的打印都是1000,栈区的a也因为block中的a(堆区)修改而改变了。

相关文章

  • OC:深入探究 block

    主要分析了block在持有__block、__weak、__strong修饰的对象时,block结构发生的变化。 ...

  • Block结构分析

    将Xcode中文件转换为C++文件 第一步:打开终端,输入xcodebuild -showsdks 展示sdks...

  • 九、Block之(一)Block内部结构及调用本质

    一、Block内部数据结构 1.调用分析 2.关于block调用中 block->FunPrt()的理解 bloc...

  • 尝试分析Block结构

    将以下代码变换为C++源代码,使用“clang -rewrite-objc main.m”操作。说是C++,其实也...

  • 5. block

    目录 Block底层解析什么是block?block编译转换结构block实际结构block的类型NSConcre...

  • Block技巧与底层解析

    目录 Block底层解析什么是block?block编译转换结构block实际结构block的类型NSConcre...

  • swift底层探索 09 - Block捕获外界变量原理

    本文中分析两个问题:1. Block闭包是一个引用类型2. Block捕获外部变量 1、Block结构 1.1 I...

  • Block理解

    1: 什么是block?1.0: Block的语法1.1: block编译转换结构1.2: block实际结构 2...

  • block源码分析一

    源码结构分析部分 1.block实际的结构体部分(本体) 首先impl和Desc也是两个结构体,而__main_b...

  • 探究block本质

    记录一下,分六个方面来探究block,一步步分析。 一.block底层结构写一个最简单的block: c++重写:...

网友评论

      本文标题:Block结构分析

      本文链接:https://www.haomeiwen.com/subject/xhxrzftx.html