Block底层原理读书笔记-《高级编程- iOS与OS多线程和内存管理》(更新中)

2023-11-05

1 一个Block 真正的底层都有些什么?

Block会被解析成一个结构体(这里成为Block结构体),这个结构体里有:

(1)isa指针(说明Block的本质是一个对象):指向Stack、堆

(2)有函数指针(这个函数指针指向一个函数体,该函数体的内容就是Block函数体的内容)。该函数的【参数表】里面有一个参数为【这个Block结构体类型】的参数,在调用这个Block 函数的时候,会把该函数所属Block结构体作为参数值传入。函数可通过这个Block参数读取里面的捕获变量。这就是实现捕获外部变量的手段。

(3)如果Block有使用到外部变量,该结构体还会有捕获的变量(以结构体成员变量的形式存在,使用到的外部变量有多少个,就有多少个成员变量)捕获变量在结构体里面的声明没有改变。(就是跟Block捕获到的时候的声明一模一样)

2 Block捕获变量

【Block捕获自动变量(正常的Block,没有__block介入)】:Block使用到的变量会被存储(值拷贝)到Block结构体实例(的成员变量/属性)中。这个捕获发生在Block创建的时候(即:将捕获到的值传递给【Block结构体】的构造函数进行保存)。

 

2.1 在Block内改变捕获变量的值

在Block内可以改变【Block外部变量的值】的方式:

(1)C语言的:静态(局部)变量、静态全局变量、全局变量(P103-P104)

(2)使用__block说明符

 【Block不捕获全局变量】:Block 只会捕获局部变量,对于全局变量、全局静态变量,是不会捕获的。这些全局变量的作用域是全局的,在Block中也能生效。

【Block捕获局部静态变量】:捕获的是该变量的指针(该变量地址)

【Block捕获__block修饰的变量】:__block 的变量会变成一个__block结构体(含有isa指针)P105,该结构体内部保存了捕获的变量值(__block结构体成员变量)。Block捕获的是该结构体指针。

2.2 OC中的存储域类说明符(__block)

所谓存储域类说明符,就是指定将变量值存放到哪个存储区域中(堆、栈、寄存器)

C语言中,存储域类说明符有:

extern:声明所修饰的内容(变量/函数)能否为外部文件访问——变量/函数作用域

static:(修饰变量的时候)表示作为静态变量存储在静态变量区;修饰函数的时候,表示该函数只能在当前文件内访问,外文文件不可访问——函数作用域

auto:表示作为自动变量存储在栈中

register:表示尽可能将变量存储到CPU寄存器中

2.3 对捕获变量使用__block带来的改变

(1)【使用__block前】:捕获的变量是通过【值传递】赋值给Block结构体内的属性A(通过构造函数)进行保存,在Block函数体内又通过【值传递】(读取Block结构体的A属性)赋值给捕获的变量,这都是只读的,因此,我们在Block函数内不能修改捕获变量的值,否则在编译的时候就会报错。

 

(2)【使用__block后】:被捕获的变量不再是简单的值传递。而是在此之前,生成一个专属的【捕获变量结构体】,在该结构体中,持有与原捕获变量一摸一样的结构体成员。前面所说的在底层上对捕获变量的所有操作,都是在操作这个新创建的【捕获变量结构体】内保存的结构体成员。如此一来,通过修改【捕获变量结构体】中的结构体成员,就可以达到在Block内修改捕获变量的目的。 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Block底层原理读书笔记-《高级编程- iOS与OS多线程和内存管理》(更新中) 的相关文章

  • 如何在 Swift 4 中以编程方式将 IBAction 添加到 uibutton?

    如何以编程方式将 IBAction 添加到 uibutton button addTarget self action Selector buttonAction for touchUpInside func buttonAction se
  • 当我启动项目时没有 viewcontroller.swift 文件 [重复]

    这个问题在这里已经有答案了 我尝试启动该项目并使用视图控制器 但我没有看到它 仅appdelegate和scenedelegate和contentview 下面的代码应该添加到视图控制器中 但我不知道添加到哪里 它不断给我一条错误消息 指出
  • 将 NSDate 转换为 SWIFT 中具有特定时区的字符串

    在我的核心数据库中 我有一个带有 NSDate 属性的 新闻 实体 我的应用程序遍布全球 新闻已发布2015 09 04 22 15 54 0000法国时间 GMT 2 为了保存日期 我将其转换为 UTC 格式 let mydateForm
  • 我以前没见过的 CGRect 语法

    我在一些示例代码中看到了下面的语法 但不确定我是否理解它 CGRect imageRect CGRect size baseImage size 这只是初始化的一种简写方式吗CGRect相当于 CGRect imageRect CGRect
  • 如何创建一个 NSMutableArray 并为其分配一个特定的对象?

    我刚刚开始接触 Obj C 并且希望创建一个 MKAnnotations 数组 我已经创建了名为的 MKAnnotation 类TruckLocation其中包含名称 描述 纬度和经度 这是到目前为止我所拥有的数组 NSMutableArr
  • iOS UITableViewCell需要按两次才能调用didSelectRowAtIndexPath

    我有一个 UITableView 有时需要您触摸它两次才能选择一个单元格 更多细节 仅当表格一直向上或一直向下滚动后才需要两次触摸 只需第二次触摸即可呼叫didSelectRowAtIndexPath 当表格以自然的 向上滚动位置 打开时
  • 如何自定义 NSSlider

    我正在尝试在 Cocoa 中实现一个具有 5 个值的自定义滑块 查看我的演示项目 可以在此处下载 http s000 tinyupload com index php file id 07311576247413689572 http s0
  • 核心蓝牙在后台进行广告和扫描

    我一直在尝试设置一个应用程序 使设备既扫描外围设备又作为外围设备进行广告 目标是当两个设备通过蓝牙发现彼此靠近时在后台被唤醒 从 Apple 文档来看 您似乎应该能够在后台运行 BLE 启用蓝牙中心和蓝牙外设后台模式 并且当一台设备位于前台
  • 如何在 Monotouch 中对 UIImageView 进行运动模糊效果?

    在 MonoTouch 中进行实时运动模糊的方法是什么 当滚动惯性图片库时 我需要在 UIImageView 上应用运动模糊效果 以强度和方向作为参数 就像在 Photoshop 中一样 我在 CocoaTouch 或 CoreAnimat
  • 如何修复C风格的for语句?

    什么是正确的修复方法C 风格的 for 语句对于下面发布的代码 目前我正在交战 C 风格的 for 语句已弃用 并将在将来删除 斯威夫特的版本 var ifaddr UnsafeMutablePointer
  • CoreAnimation 性能分析 - CAReplicatorLayer 与 CAShapeLayer

    我正在制作一个依赖 CoreAnimation 的应用程序 它有一个 CAReplicatorLayer 和一个 CAShapeLayer 作为子层 当进行 12 次复制 然后对路径进行动画处理 在 touchMoved 上更改它 时 一旦
  • 使用prefersLargeTitles 和 UITableView 平滑滚动

    我在使用时遇到了滚动问题prefersLargeTitles并添加了UITableView 如果我设置prefersLargeTitles在导航控制器中 其根是UITableViewController一切都很好 导航大标题的滚动方式与我们
  • 找不到导航对象。您的组件是否位于导航器屏幕内?

    在我下面的代码中 当我使用 useNavigation 时 它会给出像我的问题一样的错误 如何使用useNavigation 请任何人都可以解决此错误 错误 找不到导航对象 您的组件是否位于导航器屏幕内 我从这里跟踪了代码https rnf
  • 使用 Parse.com 上传视频

    我是解析新手 正在尝试保存视频并将其上传到云端 这是我正在使用的代码 但是当调用 didButtonAction 时 它不断收到错误 我相信问题出在将视频保存为文件时 但我不知道如何解决这个问题 先感谢您 void imagePickerC
  • Xcode 不会在故事板中显示我的文本字段占位符文本

    当我在属性检查器中分配文本字段的占位符值时 它不会显示在故事板中 但是 当我运行应用程序的模拟器时 它就在那里 我缺少什么设置吗 我只想能够在编辑器中看到占位符文本 下面是 xcode 和模拟器之一的屏幕截图 我遇到了同样的问题 幸运的是我
  • 自动布局:Y 位置为两个值中的最大值

    我有一个按钮 play Button 和两个 UIView myView 1 和 myView 2 它们的位置在执行过程中可能会发生变化 我希望 playButton 的顶部比 UIView 1 的底部或 UIView 2 的底部低 10
  • Swift 3 '[UIApplicationLaunchOptionsKey:任意]?'无法转换为 '[String : NSString]'

    我有一个 TVOS 应用程序已从 Swift 2 转换为 Swift 3 但出现以下错误 我不确定如何让它安静下来 UIApplicationLaunchOptionsKey 任意 无法转换为 String NSString 它出现在这段代
  • 在 UITableviewCell 高度动画的同时动画 CALayer 阴影

    我有一个 UITableView 我正在尝试使用它来展开和折叠beginUpdates and endUpdates方法并在发生时显示阴影 在我的自定义 UITableViewCell 中 我有一个图层 我为其创建阴影layoutSubvi
  • 我可以在 NS_SWIFT_NAME 中使用保留关键字吗?

    我正在尝试使 Objective C 委托协议更漂亮以便在 Swift 中使用 但我在弄清楚如何使用时遇到了一些麻烦NS SWIFT NAME 是否可以使用NS SWIFT NAME指定 Swift 名称中与 Objective C 关键字
  • 应用程序图标未刷新

    我更改了新版本应用程序中的图标图像 并且我在设备中安装了旧版本应用程序 然后我安装了新版本 它在 iOS 5 中运行良好 但在 iOS 6 中 图标没有刷新 它仍然显示旧版本图标 徽标 如果没有安装旧版本应用程序 该设备在 iOS 5 和

随机推荐