BLOCK

作者: 豆豆哥哥 | 来源:发表于2019-05-20 10:11 被阅读0次

Block就是一个里面储存了指向函数体中包含定义block时的代码块的函数指针,以及block外部上下文变量等信息的结构体

1.为什么说Block是Objc对象 及内存分布

可以通过object_getClass 来获取对象的class

    void(^blockName)() = ^() {
        
    };
    Class blockClass = object_getClass(blockName);
    while (blockClass) {
        NSLog(@"%@",blockClass);
        blockClass = class_getSuperclass(blockClass);
    }

image.png

总结: 有类的层级结构所以说是一个类

block的内存分布

有3种

globalBlock 全局
mallocBlock 堆区
stackBlock 栈区

1.没有外部变量的block都是globalBlock
2.有外部的变量有2种

2.1全局变量,静态变量,局部静态变量,
 都是globalBlock
2.2普通外部变量,strong 和copy 修饰的是一样的放在堆区了,weak 放在栈区  (会被释放) 再次调用会造成野指针访问 如2.2图
2.2.png

3.block自定义的函数的参数的时候,block会在栈区,但是你调用了系统的方法,block就会自动copy变成mallocblock
4.block作为返回值的时候是在堆区的


image.png

2.不同block的结构


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

把.m文件变成C++文件
clang --help
-rewrite-objc Rewrite Objective-C source to C++

注意不是底层实现代码,是C++的实现代码,一定程度上能了解block在C++上怎么实现的 ,进而推断Block在运行时都干了什么

1.block

int age = 10;
 void(^blockName)() = ^() {
        NSLog(@"%d",i);
    };

生成C++摘取主要的代码

struct __blcok_impl{
 void *isa;//存放block 是那个block的(globle,stack malloc)
    int Flags;
    int Reserved;
    void *FuncPtr;//执行函数的指针
}

struct __main_block_desc_0 {
    size_t reserved;
    size_t Block_size;
};

struct __main_block_impl_0 {
    struct __block_impl impl;
    struct __main_block_desc_0* Desc;
    int a;
    // C++ 的构造函数
  //Fp 是要执行函数的指针
  //desc 描述block的
  //_age 外部捕获的参数
    __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc,int _age, int flags=0):age(_age)  {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};
//执行的函数 其对应的就是*fp
static void __main_block_func_0(struct __main_block_impl_0 *__cself){

 }

static struct __main_block_desc_0 {
  size_t reserved;
  size_t Block_size;
} __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0)};

//定义block变量
void (*block)(void) = &__main_block_impl_0(
__main_block_func_0, 
&__main_block_desc_0_DATA);
// block 的调用
block->FuncPtr(block);

这样的话,我们就可以通过 void (*block)(void) 来接收这个结构体的地址,通过调用这个 FuncPtr 来调用函数。


结构.png

2捕获外部变量

1.空的block
2.包含简单类型(int等)block //值的捕获, 离开作用域就会销毁
3.包含临时的objc对象的block //对象的地址捕获 ,离开作用域就会销毁
4.成员变量 //成员变量的object 的捕获
5.包含__block的变量 //生成结构图
6.global value //直接使用 不用捕获
7.全局static value //直接使用不用捕获
8.局部static value //指针传递

3.__block的作用

修饰基本数据类型

 __block int a = 8;
        void (^block)(void) = ^{
            a = 10;
            NSLog(@"------");
        };
        
        block();
        NSLog(@"-----%d",a);

首先经过 __block 修饰的 int a 会被转换为一个结构体__Block_byref_a_0 a,并将给这个结构体赋值

struct __Block_byref_a_0 {
  void *__isa;
__Block_byref_a_0 *__forwarding;
 int __flags;
 int __size;
 int a;
};

__Block_byref_a_0 a = {
                         0,
                         &a,
                         0,
                         sizeof(__Block_byref_a_0),
                        8};

接下下来在void (^block)(void) 中给 a 赋值,通过 a->__forwarding->a,即:

static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
  __Block_byref_a_0 *a = __cself->a;
   (a->__forwarding->a) = 10;
}
用__blcok修饰的基本数据类型

基本数据类型用__block修饰后,会生成2个一样结构的struct 一个放在栈区代替 基本数据,另一份拷贝堆区,让block能访问,通过struct中的__forwading 属性栈区的指向堆区的struct的地址,堆区的指向自己的地址,
实现 在堆区和栈区修改变量的值保持数据的一致性.

解决循环引用

__weak
__>unsafe_unretained
__b>lock

MRC 情况下 __block 不会对外部的变量产生强引用

总结:Block就是一个里面储存了指向函数体中包含定义block时的代码块的函数指针,以及block外部上下文变量等信息的结构体

ARC 下 修饰block 使用 strong 和 copy 没有区别,都会将栈上的拷贝到堆上
MRC 下 strong 强引用 copy 会将栈上的拷贝到堆上

相关文章

  • iOS开发之Block原理探究

    Block概述 Block本质 Block调用 Block分类 Block循环引用 Block原理探究 Block...

  • block的使用

    定义block 返回类型 (^block名称)(参数) = ^(){block内容}; 调用block block...

  • Block 02 - __block

    Block 02 - __block __block 的作用 __block 可以解决 Block 内部无法修改 ...

  • iOS面试之Block大全

    Block Block内容如下: 关于Block 截获变量 __block修饰符 Block的内存管理 Block...

  • iOS面试之Block模块

    Block Block内容如下: 关于Block 截获变量 __block修饰符 Block的内存管理 Block...

  • iOS Block

    Block的分类 Block有三种类型:全局Block,堆区Block,栈区Block 全局Block 当Bloc...

  • iOS block 为什么官方文档建议用 copy 修饰

    一、block 的三种类型block 三种类型:全局 block,堆 block、栈 block。全局 block...

  • iOS开发block是用copy修饰还是strong

    Block分为全局Block、堆Block和栈Block1、在定义block没有引用外部变量的时候,block为全...

  • block 初探

    全局block, 栈block, 堆block

  • Block

    一、Block本质 二、 BlocK截获变量 三、__block 修饰变量 四、Block内存管理 五、Block...

网友评论

      本文标题:BLOCK

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