Block详解二(底层分析)
Block专辑:
今天讲述Block的最后一篇,后两篇仅仅是加深1,2篇的理解,废话少说,开始讲解!
- __block细节
- __block内存管理
- 循环引用问题
一:__block细节
大家可能会遇到下面的问题,block的内部想要修改外部的auto变量,但是编译器会报问题!如下
如果block内部想要修改外部的auto变量,可以在int age 前面加入static修饰词,变为静态局部变量(会一直存在内存中,反而不好),以及可以将int age代码移植到函数外面变为全局变量! 除此之外还有没有其他的做法了呢,显然是有的,通过__block修饰,如下:
发现__block修改外面变量是可以达到目的的! 小结论
- __block可以用于解决block内部无法修饰auto变量值的问题
- __block不能修饰全局变量、静态变量(static)
- 编译器会将__block变量包装成一个对象
通过命令
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m
生成main.cpp代码查看原理
上面提到可以将int main函数的代码简化一下,简化成如下
首先拿到forwarding指针然后再拿到age的值
二:__block的内存管理
1. 当block在栈上时,并不会对__block变量产生强引用;
2. 当block被copy到堆时
- 会调用block内部的copy函数
- copy函数内部调用_Block_object_assign函数
- _Block_object_assign函数会对__block变量形成强引用(retain)
3.当block从堆中移除时
- 会调用block内部的dispose函数
- dispose函数内部会调用_Block_object_dispose函数
- _Block_object_dispose函数会自动释放引用的__block变量(release)
拓展:__block的_forwarding指针
栈上block的forwarding指针指向堆上的block,而堆上block的forwarding指针指向自己本身的指针。
三:循环引用
关于block循环引用的基本概念,专辑block已经讲解,本篇讲述核心内容
1. 解决循环引用问题-ARC
(1) 用__weak、__unsafe_unretained解决
下面用例子来巩固下
int main(int argc, const char * argv[]) {
@autoreleasepool {
Person *person = [[Person alloc]init];
__weak Person *weakPerson = person;
person.block = ^{
NSLog(@"age is %d", weakPerson.age);
};
}
NSLog(@"");
return ;
} #import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
typedef void(^ZXYBlock)(void);
@interface Person : NSObject
@property(nonatomic,copy)ZXYBlock block;
@property(assign, nonatomic)int age;
@end #import "Person.h"
@implementation Person
-(void)dealloc {
NSLog(@"%s", __func__);
}
@end
__weak方式解决循环引用问题
__unsafe_unretained方式解决循环引用问题
__weak,__unsafe_unretained都可以解决循环引用,有什么区别呢?
结论
相同点:__weak和__unsafe_unretained都不会产生强引用
不同点:__weak指向对象销毁时,会自动让指针置为nil;__unsafe_unretained不安全,指向对象销毁时,指针存储地址 不变,如果再次访问可能会造成野指针
(2) 用__block方式解决
下面来探究一下为什么__block可以解决循环引用?看下编译成的c++代码
以前结合__block 对象变量以及__block自动变量可知:c++包含了三个对象,如下
上面的三种关系如下,调用person = nil就是为了打断其中一个循环引用链条,但是必须要调用block()
2. 解决循环引用问题-MRC
MRC下,首先要在编译器上设置为MRC环境。Build Settings->Automatic Reference Counting设为No
(1) 用__unsafe_unretained解决
因为MRC下不存在弱指针,所以不存在__weak修饰解决循环引用
(2) 用__block解决
总结
上面是block最后一篇的讲解,关于block总共有四篇博客,应该可以讲解完所有关于block的内容,应该会大大增加大家对block底层的理解,如果觉得有意义有所帮助,欢迎点赞和关注,本人会及时更新博客!!!
Block详解二(底层分析)的更多相关文章
- Block详解一(底层分析)
本篇博客不再讲述Block的基本定义使用,最近而是看了很多的block博客讲述的太乱太杂,所以抽出时间整理下block的相关底层知识,在讲述之前,提出几个问题,如果都可以回答出来以及知道原理,大神绕过 ...
- 关于syslog日志功能详解 事件日志分析、EventLog Analyzer
关于syslog日志功能详解 事件日志分析.EventLog Analyzer 一.日志管理 保障网络安全 Windows系统日志分析 Syslog日志分析 应用程序日志分析 Windows终端服务器 ...
- PopUpWindow使用详解(二)——进阶及答疑
相关文章:1.<PopUpWindow使用详解(一)——基本使用>2.<PopUpWindow使用详解(二)——进阶及答疑> 上篇为大家基本讲述了有关PopupWindow ...
- Android View 的绘制流程之 Layout 和 Draw 过程详解 (二)
View 的绘制系列文章: Android View 的绘制流程之 Measure 过程详解 (一) Android View 绘制流程之 DecorView 与 ViewRootImpl 在上一篇 ...
- LinkedList详解-源码分析
LinkedList详解-源码分析 LinkedList是List接口的第二个具体的实现类,第一个是ArrayList,前面一篇文章已经总结过了,下面我们来结合源码,学习LinkedList. 基于双 ...
- .NET DLL 保护措施详解(二)关于性能的测试
先说结果: 加了缓存的结果与C#原生代码差异不大了 我对三种方式进行了测试: 第一种,每次调用均动态编译 第二种,缓存编译好的对象 第三种,直接调用原生C#代码 .net dll保护系列 ------ ...
- iOS开发——Block详解
iOS开发--Block详解 1. Block是什么 代码块 匿名函数 闭包--能够读取其他函数内部变量的函数 函数变量 实现基于指针和函数指针 实现回调的机制 Block是一个非常有特色的语法,它可 ...
- Android 布局学习之——Layout(布局)详解二(常见布局和布局参数)
[Android布局学习系列] 1.Android 布局学习之——Layout(布局)详解一 2.Android 布局学习之——Layout(布局)详解二(常见布局和布局参数) 3.And ...
- logback -- 配置详解 -- 二 -- <appender>
附: logback.xml实例 logback -- 配置详解 -- 一 -- <configuration>及子节点 logback -- 配置详解 -- 二 -- <appen ...
随机推荐
- html常用事件
1.onblur 当窗口失去焦点时运行 2.click 点击鼠标触发的事件 3.onfocus 当窗口获得焦点时运行 4.oninput 当元素获得用户输入时运行 5.onsubmit 当提交表单时运 ...
- MyEclipse提示Errors occurred during the build
最近在使用Extjs 在springsource Tool Suite运行时老是出现: Errors occurred during the build. Errors running builder ...
- Pip安装TensorFlow报错:MemoryError
问题描述 使用pip安装TensorFlow时,一直报错,情况如下: 解决办法 使用如下命令可正常安装: pip3 install --no-cache-dir tenstoflow --no-cac ...
- 空间数据导入Oracle数据库备忘
- 【01】React 环境搭建
react来自于Facebook公司的开源项目 react 组件化模块化 开发模式 react通过对DOM的模拟(虚拟dom),最大限度地减少与DOM的交互 (数据绑定) react 基于jsx的 ...
- 机器学习- RNN以及LSTM的原理分析
概述 RNN是递归神经网络,它提供了一种解决深度学习的另一个思路,那就是每一步的输出不仅仅跟当前这一步的输入有关,而且还跟前面和后面的输入输出有关,尤其是在一些NLP的应用中,经常会用到,例如在NLP ...
- 基于abp框架的数据库种子数据初始化
目录 基于abp框架的数据库种子数据初始化 1.背景 2.参照 3.解决方案 3.1 初始化数据 3.2 依赖注入方法容器里获取数据库上下文 3.3 封装创建初始化数据列表方法 3.4 数据库中没有的 ...
- 前端基础知识之HTML
[1: What does a doctype do?] 1: doctype是html文件的第一行代码,意味着它的前面有注释都不行.所以要要写在<html>标签前面,而且它不属于html ...
- Python - requests发送请求报错:UnicodeEncodeError: 'latin-1' codec can't encode characters in position 13-14: 小明 is not valid Latin-1. Use body.encode('utf-8') if you want to send it encoded in UTF-8.
背景 在做接口自动化的时候,Excel作为数据驱动,里面存了中文,通过第三方库读取中文当请求参数传入 requests.post() 里面,就会报错 UnicodeEncodeError: 'lati ...
- 基于Modelsim的直方图统计算法仿真
一.前言 本篇主要针对牟新刚编著<基于FPGA的数字图像处理及应用>第六章第五节中直方图统计相关类容进行总结,包括代码实现及 基于Modelsim的仿真.书读百遍,其意自现. 2020-0 ...