__Block 修饰符

Block 想要改变外部的变量,必须要用__Block 来修饰自动变量。

根据内存地址可以看出来,__block 所修饰的变量,将外部的变量在栈中的内存地址放到了堆中。

        // auto 自动变量的内存分配在栈区域 stack__block int meters = 1000;// 在block 引用之前 0x7ffeefbff4f8NSLog(@"在block 引用之前 %p",&meters);// 3 无返回值无参数void (^Run1)(void) = ^{meters = 2000;// 在block 引用之后 0x100502ac8NSLog(@"在block 引用之后 %p",&meters);NSLog(@"i have run %d meters",meters);} ;Run1();

转为C++ 代码 看出

meter 是如何改变的

先是找到 __forwarding 结构体,然后的话再去找打结构体内部的meter 属性

(meters->__forwarding->meters) = 2000;

struct __main_block_impl_0 {struct __block_impl impl;struct __main_block_desc_0* Desc;__Block_byref_meters_0 *meters; // by ref__main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, __Block_byref_meters_0 *_meters, int flags=0) : meters(_meters->__forwarding) {impl.isa = &_NSConcreteStackBlock;impl.Flags = flags;impl.FuncPtr = fp;Desc = desc;}
};// meter 包装成一个对象,里面是含有一个isa 指针的
struct __Block_byref_meters_0 {void *__isa;
__Block_byref_meters_0 *__forwarding;int __flags;int __size;int meters;
};//meter 是如何改变的static void __main_block_func_0(struct __main_block_impl_0 *__cself) {__Block_byref_meters_0 *meters = __cself->meters; // bound by ref(meters->__forwarding->meters) = 2000;}
  • 1 在ARC 环境下,Block 被引用的时候,会被Copy 一次,由栈区Copy 到堆区域

  • 2 在Block 被Copy的时候,Block 内部的变量也会被copy 一份到堆上面

  • 3 被__Block 修饰的变量,在被Block 引用的时候,会变成结构体也就是OC的对象,里面的————forwarding 指针由栈copy 到堆上面

  • 4 栈上__block 变量结构体中,__forwarding的指针指向堆上面__block 变量结构体,堆上的__block 变量结构体中的

    __forwarding 指针指向自己

  • 5 当block 从堆中移除的时候,会调用block 内部的dispose 函数,dispose函数内部会调用_Block_object_dispose函数,_Block_object_dispose函数会自动释放引用的__block变量(release)

图片

Block 底层值__Block修饰符相关推荐

  1. Block截获自动变量实现与__block修饰符内部实现

    Block自动截获变量 在Block中访问一个外部的局部变量,Block会持用它的临时状态,外部局部变量的变化不会影响它的的状态. eg: typedef void(^WxsBlock) ();- ( ...

  2. java重写——返回值、修饰符

    返回值类型: 在java5或者以前,必须一样.java7.java8可以不同,但必须是父类返回值的派生类 修饰符: 子类重写父类的方法访问修饰,不能低于父类的方法访问修饰权限.

  3. ios Block底层详解、框架结构:捕获、对象类型、__block、__forwarding、循环引用

    1:捕获 2:block类型 2.1:问题 :mrc环境下  下面讲的都是mrc环境下,会真实很多 2.2:在arc下,block 自动加上copy的情况---:返回block. 2.3:在arc下, ...

  4. __block和__weak修饰符的区别

    block下循环引用的问题 __block本身并不能避免循环引用,避免循环引用需要在block内部把__block修饰的obj置为nil __weak可以避免循环引用,但是其会导致外部对象释放了之后, ...

  5. 7 类与对象,方法和函数的定义和使用,返回值,权限修饰符 public default protected private(重点)

    文章目录 1 面向对象 1 面向对象概述 2 类与对象 2.1 概述 2.2 Java中类的定义万物皆对象. 2.3Java中对象的定义和使用 3 方法和函数的定义和使用 3.1 什么是方法,函数 3 ...

  6. Java学习系列(四)Java面向对象之修饰符、封装、继承、多态详解

    今天内容比较多,直接步入正题吧. 类和对象的定义 类是现实世界或思维世界中的实体在计算机中的反映,它将数据以及这些数据上的操作封装在一起.而对象是具有类类型的变量,存在于堆内存中.类是对象的抽象,而对 ...

  7. Java面向对象之修饰符、封装、继承、多态详解

    类和对象的定义 类是现实世界或思维世界中的实体在计算机中的反映,它将数据以及这些数据上的操作封装在一起.而对象是具有类类型的变量,存在于堆内存中.类是对象的抽象,而对象是类的具体实例.类是抽象的,不占 ...

  8. 深入浅出OOP(五): C#访问修饰符(Public/Private/Protected/Internal/Sealed/Constants)

    访问修饰符(或者叫访问控制符)是面向对象语言的特性之一,用于对类.类成员函数.类成员变量进行访问控制.同时,访问控制符也是语法保留关键字,用于封装组件. Public, Private, Protec ...

  9. vue与elementUI中给el-input绑定键盘按键--按键修饰符

    vue怎么写键盘事件 vue允许将按键值作为修饰符来使用,如监听回车事件,有两种写法,如下代码: <input type="text" @keyup.13="con ...

最新文章

  1. linux c warning: implicit declaration of function 'strtok_r'解决方案
  2. ios14的蓝牙弹窗_iOS14来了,总结一下给你带来了哪些最实用的功能
  3. spring 配置文件模板
  4. 磁盘的磁道(Track)
  5. 纽曼皮尔逊准则Matlab实现,纽曼-皮尔逊准则,Neyman Pearson Criterion,在线英语词典,英文翻译,专业英语...
  6. [转载] Python中pass的作用
  7. 新版《谷歌搜索引擎优化初学者指南》
  8. MySQL -- 行转列 -- GROUP_CONCAT -- MAX(CASE WHEN THEN)
  9. command -- 把动作封装成类
  10. 【转】SVN中的Branches分支以及Tags标签详解与应用举例
  11. c#中接口的使用方法图解_C#中的接口interface的使用
  12. 李宏毅机器学习笔记【未完】
  13. 电商后台管理系统项目介绍和项目初始化
  14. 学信号处理要理解均值、平均偏差、标准差、方差
  15. dhcp服务器自动分配dns,一文了解如何使用DHCP自动分配IP地址?
  16. 理解 this.initialize.apply ( this, arguments )
  17. 峰值帧+时序信息 跨数据集微表情识别
  18. 本世纪,佛祖派机器人来弘扬佛法
  19. mysql查询每行重复_MySQL查询返回重复的行
  20. 12、python 海龟绘图 turtle

热门文章

  1. Xdebug的安装-(无错可执行版)
  2. Linux环境编程--进程通信
  3. 详解Apache下.htaccess文件常用配置
  4. Jmail的主要参数列表
  5. 指针的本质2-void和void*及其应用在nginx中的应用
  6. 使用多线程还是用IO复用select/epoll? epoll 或者 kqueue 的原理是什么?
  7. VC开发Windows客户端软件之旅——前言
  8. CUDA Samples: Streams' usage
  9. tiny-cnn执行过程分析(MNIST)
  10. 设计模式之适配器模式(Adapter)摘录