2026/5/21 15:47:14
网站建设
项目流程
网站开发背景设置,wordpress liuweili,南京做网站的公司排名,网站拓扑图怎么做[iOS原理] Block的本质 文章目录[iOS原理] Block的本质前置研究iOS内存五大分区栈区堆区全局区 / 静态区常量区代码区isa指针BlockBlock的本质Block的三种类型__block的本质ARC 在某些情况下会对 block 自动进行一次 copy 操作#xff0c;将其从栈区移动到堆区Block的应用及其…[iOS原理] Block的本质文章目录[iOS原理] Block的本质前置研究iOS内存五大分区栈区堆区全局区 / 静态区常量区代码区isa指针BlockBlock的本质Block的三种类型__block的本质ARC 在某些情况下会对 block 自动进行一次 copy 操作将其从栈区移动到堆区Block的应用及其注意事项“心理史学……盖尔·多尼克将其定义为数学的一个分支专门处理人类群体对特定的社会与经济刺激所产生的反应……”“在这门学科的定义中隐含着一个假设即作为研究对象的人类汇集必须大到足以用统计学的方法来处理。集结的人数由许许多多的‘阿西莫夫系数’Asimov coefficient决定。群体越大预测的准确性就越高。”——摘自《银河百科全书》第116版上一篇博客里我们简单讲解了Block的用法这篇里我们来讲解一下Block的本质及其实现在讲本质之前我们先来复习学习几个前置概念前置研究iOS内存五大分区iOS内存我们之前有讲过底层的分配逻辑我们现在来讲讲它的内存布局内存分区分为栈区堆区全局区 / 静态区常量区代码区想要判断一块数据在哪一部分只需要使用lldb指令frame variable -L来查看即可栈区栈区内存由系统自动分配和释放不需要我们操心它的存取速度极快一般来说负责存放函数的参数和函数内部定义的局部变量堆区内存由程序员手动管理ARC时代虽然编译器帮我们插入了retain/release但本质上还是需要管理的笑如果处理不好出现野指针或者内存泄露就不好了速度相对栈区要慢一般存放通过alloc,new,copy,mutableCopy等创建的对象全局区 / 静态区全局区 / 静态区部分程序运行期间一直存在直到App退出才会被释放它分为BSS未初始化和Data已初始化部分一般来说存放全局变量和静态变量常量区常量区的数据只读不可被修改一般存放常量字符串如Hello或者const修饰的全局变量一旦编译完成其中的内容就无法再修改了代码区代码区跟上面比起来更像是规则而不是数据它同样可读不可写它里面存放的东西是编译之后的二进制代码isa指针isa指针可以说是 Objective-C Runtime运行时机制的关键部分简单来说它是一张身份证上面记载了所属对象的类别和其他信息它告诉系统我是谁属于什么类最关键的一点在于isa构成了oc中查找方法的路径对于block的原理来讲我们现在先只复习这么多就足够了BlockBlock的本质Block有的时候我们说可以把它的返回类型当作它的类型来用有的时候说它是一种函数我们使用clang指令将oc转换为C可以看出// Block 的底层结构体struct__main_block_impl_0{struct__block_impl impl;// block 的基本信息包含 isastruct__main_block_desc_0*Desc;// 描述信息大小等intage;// 捕获的外部变量// 构造函数__main_block_impl_0(void*fp,struct__main_block_desc_0*desc,int_age,intflags0):age(_age){impl.isa_NSConcreteStackBlock;// isa 指针impl.FuncPtrfp;// 函数指针指向具体执行的代码// ...}};Block是有isa指针的即它是一个对象再观察覆写出的C代码找到其中的FuncPtr编译器会把 Block 花括号{ ... }里的代码提取出来封装成一个静态 C 函数然后让FuncPtr指向这个函数。调用 Block本质上就是通过函数指针调用这个 C 函数那关于捕获外部变量Block又是如何实现的呢继续观察覆写代码结构体里的int age;即为Block捕获的外部变量当你定义 Block 时它把外部的age变量的值拷贝到了自己的结构体里之后无论外面的age怎么变Block 结构体里的age依然是 10Block的三种类型Block作为对象在内存中也有位置根据它的位置不同Block分为三种_NSConcreteGlobalBlock(全局 Block)位置数据区Data段。特点没有访问任何外部局部变量或者只访问了全局变量/静态变量。相当于一个单例整个 App 生命周期都在_NSConcreteStackBlock(栈 Block)位置栈区。特点访问了外部局部变量。这是最危险的因为栈内存由系统自动释放。如果作用域结束Block 就没了再调用就会 Crash注意在 ARC 环境下编译器会自动帮我们将栈 Block 拷贝到堆上所以我们现在很少见到纯粹的栈 Block 了_NSConcreteMallocBlock(堆 Block)位置堆区。特点由栈 Block 调用copy而来。它的生命周期由引用计数管理我们现在的 Block 属性都用copy修饰就是为了把它搬到堆上防止被销毁__block的本质之前讲过直接在block里修改外部局部变量会报错必须加入__block修饰符在默认情况下Block捕获的是变量的值是只读的在加入__block后编译器会生成一个新的结构体对象并把原来的值变量将入到这个对象里这样它的本质是将值传递变成指针传递ARC 在某些情况下会对 block 自动进行一次 copy 操作将其从栈区移动到堆区出现以下情况时ARC会自动对block执行一次copy操作将其从栈区移动到堆区当block作为函数返回值时当block被强指针引用时当 Cocoa API 方法名包含usingBlock且block作为参数时或block作为GCD API方法参数Block的应用及其注意事项作为iOS开发人员对Block的使用一定是要达到精通程度的Block的应用场景很广首先就是函数思想利用它作为一个匿名函数的性质来保存代码块灵活操作但在架构层次中如果你的嵌套层次非常深那么不要使用Block因为在这种情况下Block的大量使用不便与你的代码调试以及代码直观性引用资料iOS开发—Block底层详解Cocoa blocks as strong pointers vs copy