前言:

对block的简单笔记总结,

1.本质:

封装了函数调用和函数调用环境的对象
2.block结构:
3.block捕获变量:
由于需要跨函数访问变量,所以需要捕获变量,(防止访问时已被销毁)
 - auto变量(基本数据类型):值捕获,超出作用域就被销毁了
 - static变量:指针捕获,
 - 全局变量:直接访问
 - self,也属于局部变量,(每个方法默认参数(self,_cmd))
4.block类型:
block类型
环境
copy
存储区域
NSGlobalBlock
没有访问auto变量
什么也不做
程序的数据区域 .data
NSStackBlock
访问auto变量
从栈赋值到堆上
NSMallocBlock
NSStackBlock 调用copy
引用计数+1
5.block 的copy:
在ARC环境下,编译器会根据情况自动将栈上的block复制到堆上,比如以下情况:
- Block 作为函数的返回值
- 将block赋值给__strong指针时
- block 作为Cocoa API中方法名含有usingBlock的方法参数
- block作为GCD API的方法参数
6.block内部访问对象类型的auto变量:
当block内部访问了对象类型的auto变量时,
- 如果block是在栈上,将不会对auto变量进行强引用
- 如果block 被拷贝到堆上
- 会调用block内部的copy函数,
- copy函数内部调用 _Block_objct_assgin函数,
- _Block_objct_assgin函数会根据auto变量的修饰符(__strong,__weak,__unsafe_unretained)做出对应的操作,类似retain(强引用、弱应用)
如果block从堆上移除
- 会调用block中的dispose函数
- dispose函数内部调用_Block_objct_dispose函数
- _Block_object_dispose函数会自动释放引用的auto变量,类似于release
7.__block 修饰符
编译器会将__block修饰的变量包装成一个对象
  - __block 可以用于解决block内部无法修改auto变量值的问题
  - __block不能修饰 static、全局变量
- 当block在栈上是,并不会对__block对象强引用
- 如果block 被拷贝到堆上,对__block对象是强引用
- 当block被copy到堆上时,会调用block(desc)中的copy函数
- copy函数内部调用 _Block_objct_assgin函数,
- _Block_objct_assgin函数会对__block变量进行强引用(retain)
- 如果是对象类型时,在__block变量中也会存在 内存管理函数(copy,dispose)
- 当__block变量在栈中,不会对指向的对象产生强引用
- 当__block变量被copy到堆时,会调用__block中的copy函数,
- copy函数内部调用__Block_objct_assgin函数,该函数会根据对象的修饰符(__strong,__weak,__unsafe_unretained)做出对应的操作,类似retain(强引用、弱应用)(注意:仅限于ARC时会retain,MRC下不会retain)。
如果block变量从堆上移除
- 会调用block中的dispose函数
- dispose函数内部调用_Block_objct_dispose函数
- _Block_object_dispose函数会自动释放引用的__block变量,类似于release
如果是对象类型时,也会调用
- 会调用__block中的dispose函数
- dispose函数内部调用_Block_objct_dispose函数
- _Block_object_dispose函数会自动释放引用的auto变量,类似于release
注意:当block内部对应__block对象都是强引用,
struct __Block_byref_p_0 { // 包装成的结构体对象
void *__isa;
__Block_byref_p_0 *__forwarding;
int __flags;
int __size;
void (*__Block_byref_id_object_copy)(void*, void*);
void (*__Block_byref_id_object_dispose)(void*);
Person *p;
}; struct __main_block_impl_0 {
struct __block_impl impl;
struct __main_block_desc_0* Desc;
__Block_byref_p_0 *p; // by ref 指向包装成的g结构体对象指针
__main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, __Block_byref_p_0 *_p, int flags=0) : p(_p->__forwarding) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
}; static struct __main_block_desc_0 {
size_t reserved;
size_t Block_size;
void (*copy)(struct __main_block_impl_0*, struct __main_block_impl_0*);
void (*dispose)(struct __main_block_impl_0*);
}
结构:
8.__block 结构体对象内部的__forwarding指针
9.循环引用问题:
ARC:
__weak, 
__unsafe_unreatined,不会产生强引用,不安全,缺点:对象销毁后,指针不会自动指向nil
__block,缺点:必须手动调用执行block,并在block中把对象赋值nil,
MRC:
__unsafe_unretained
__block block内不会进行retain操作

iOS Block笔记总结的更多相关文章

  1. iOS学习笔记之ARC内存管理

    iOS学习笔记之ARC内存管理 写在前面 ARC(Automatic Reference Counting),自动引用计数,是iOS中采用的一种内存管理方式. 指针变量与对象所有权 指针变量暗含了对其 ...

  2. iOS回顾笔记( 01 )

    html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,bi ...

  3. iOS回顾笔记( 02 ) -- 由九宫格布局引发的一系列“惨案”

    html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,bi ...

  4. iOS回顾笔记(04) -- UIScrollView的基本使用详解

    html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,bi ...

  5. iOS回顾笔记(05) -- 手把手教你封装一个广告轮播图框架

    html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,bi ...

  6. iOS回顾笔记(06) -- AutoLayout从入门到精通

    iOS回顾笔记(06) -- AutoLayout从入门到精通 随着iOS设备屏幕尺寸的增多,当下无论是纯代码开发还是Xib/StoryBoard开发,自动布局已经是必备的开发技能了. 我使用自动布局 ...

  7. iOS回顾笔记(07) -- UITableView的使用和性能优化

    iOS回顾笔记(07) -- UITableView的使用和性能优化 如果问iOS中最重要的最常用的UI控件是什么,我觉得UITableView当之无愧!似乎所有常规APP都使用到了UITableVi ...

  8. iOS回顾笔记(08) -- 自定义Cell的类型和创建步骤总结

    iOS回顾笔记(08) -- 自定义Cell的类型和创建步骤总结 项目中我们常见的自定义cell主要分为两种 等高cell:如应用列表.功能列表 非等高cell:如微博列表.QQ聊天页面 下面对这 ...

  9. iOS回顾笔记(09) -- Cell的添加、删除、更新、批量操作

    iOS回顾笔记(09) -- Cell的添加.删除.更新.批量操作 项目中经常有对UITableViewCell做各种操作的需求: 添加一个新的cell 删除某行cell 刷新cell上某行数据(如修 ...

  10. IOS学习笔记48--一些常见的IOS知识点+面试题

      IOS学习笔记48--一些常见的IOS知识点+面试题   1.堆和栈什么区别? 答:管理方式:对于栈来讲,是由编译器自动管理,无需我们手工控制:对于堆来说,释放工作由程序员控制,容易产生memor ...

随机推荐

  1. Tomcat长轮询原理与源码解析

    Tomcat长轮询原理与源码解析 系列文章目录和关于我 零丶长轮询的引入 最近在看工作使用到的diamond配置中心原理,发现大多数配置中心在推和拉模型上做的选择出奇的一致选择了基于长轮询的拉模型 基 ...

  2. 安装vue-lic

    vue-cli是Vue.js开发的标准工具.它简化了程序员基于webppack创建工程化的Vue项目的过程.引用自vue-cli官网上的一句话:程序员可以专注在撰写应用上,而不必花好几天去纠结webp ...

  3. Network Science: 巴拉巴西网络科学阅读笔记

    前言: 最小生成树中Kruskal算法对应了统计物理中的著名模型invasion percolation.由此写了一篇文章:invasion percolation and global optimi ...

  4. lombok版本报错问题java.lang.IllegalAccessError: class lombok.javac.apt.LombokProcessor (in unnamed module

    lombok版本报错问题 记录一个项目部署时遇到的问题,我本地采用的JDK8的版本,然后我的服务器采用的是JDK17,然后在用maven进行打包的时候,发现package失败. 复现 我在本地采用的l ...

  5. 2022-10-12:以下go语言代码输出什么?A:1;B:2;C:panic;D:不能编译。 package main import “fmt“ func main() { m := m

    2022-10-12:以下go语言代码输出什么?A:1:B:2:C:panic:D:不能编译. package main import "fmt" func main() { m ...

  6. 2022-09-15:Range模块是跟踪数字范围的模块。 设计一个数据结构来跟踪表示为 半开区间 的范围并查询它们。 半开区间 [left, right) 表示所有 left <= x < righ

    2022-09-15:Range模块是跟踪数字范围的模块. 设计一个数据结构来跟踪表示为 半开区间 的范围并查询它们. 半开区间 [left, right) 表示所有 left <= x < ...

  7. 2020-01-20:mysql中,一张表里有3亿数据,未分表,要求是在这个大表里添加一列数据。数据库不能停,并且还有增删改操作。请问如何操作?

    2020-01-20:mysql中,一张表里有3亿数据,未分表,要求是在这个大表里添加一列数据.数据库不能停,并且还有增删改操作.请问如何操作?福哥答案2020-01-20: 陌陌答案:用pt_onl ...

  8. 2021-02-14:假设有排成一行的N个位置,记为1~N,N 一定大于或等于 2,开始时机器人在其中的M位置上(M 一定是 1~N 中的一个)。如果机器人来到1位置,那么下一步只能往右来到2位置;如果机器人来到N位置,那么下一步只能往左来到 N-1 位置;如果机器人来到中间位置,那么下一步可以往左走或者往右走;规定机器人必须走 K 步,最终能来到P位置(P也是1~N中的一个)的方法有多少种?

    2021-02-14:假设有排成一行的N个位置,记为1~N,N 一定大于或等于 2,开始时机器人在其中的M位置上(M 一定是 1~N 中的一个).如果机器人来到1位置,那么下一步只能往右来到2位置:如 ...

  9. Spring源码:Bean生命周期(五)

    前言 在上一篇文章中,我们深入探讨了 Spring 框架中 Bean 的实例化过程,该过程包括从 Bean 定义中加载当前类.寻找所有实现了 InstantiationAwareBeanPostPro ...

  10. 关于ESXi下如何查看磁盘SMART信息(SATA & NVMe)的教程

    ESXi下查看磁盘SMART比较麻烦,并且SATA协议的和NVMe协议的操作不一样,下面分别进行详细陈述 SATA--使用smartctl查看 本部分参考梦幻生命@CSDN(原文链接https://b ...