当前位置: 首页 > news >正文

OC对象 - Block解决循环引用

文章目录

  • OC对象 - Block解决循环引用
    • 前言
    • 1. 循环引用示例
      • 1.1 分析
    • 2. 解决思路
    • 3. ARC下
      • 3.1 __weak
      • 3.2 __unsafe_unretained
      • 3.3 __block
    • 4. MRC下
      • 4.1 __unsafe_unretain....
      • 4.1 __block
    • 5. 总结
      • 5.1 ARC下
      • 5.2 MRC下

OC对象 - Block解决循环引用

前言

本章将会通过一个循环引用案例,分析其原因,以及在ARCMRC下的解决方案

1. 循环引用示例

ZSXperson

@interface ZSXPerson : NSObject@property (nonatomic, assign) int age;
@property (nonatomic, copy) void(^block)(void);@end@implementation ZSXPerson- (void)dealloc {NSLog(@"ZSXPerson - %s", __func__);
}@end

main.m 中初始化ZSXperson对象person,创建personblock,并在block里面访问person.age

int main(int argc, const char * argv[]) {@autoreleasepool {ZSXPerson *person = [[ZSXPerson alloc] init];person.block = ^ {NSLog(@"person.age is %d", person.age);};NSLog(@"---------------");}return 0;
}

运行:

person不会销毁

1.1 分析

  • 初始化ZSXperson对象person,然后将block赋值给personblock,此时person是强引用block
  • block中,访问了person.age,因为访问了局部变量,所以block捕获了person
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc -fobjc-arc -fobjc-runtime=ios-13.0.0 main.m -o main-arm64.cpp

  • 此时blockperson的关系,是相互持有的关系

2. 解决思路

之所以叫循环引用,其实就是相互之间的引用关系形成了环

解决方式就是,断开某个引用关系,打破这个环

3. ARC下

3.1 __weak

int main(int argc, const char * argv[]) {@autoreleasepool {ZSXPerson *person = [[ZSXPerson alloc] init];__weak typeof(person) weakPerson = person;person.block = ^ {NSLog(@"person.age is %d", weakPerson.age);};NSLog(@"---------------");}return 0;
}

person正常销毁的

3.2 __unsafe_unretained

int main(int argc, const char * argv[]) {@autoreleasepool {ZSXPerson *person = [[ZSXPerson alloc] init];__unsafe_unretained typeof(person) uuPerson = person;person.block = ^ {NSLog(@"person.age is %d", uuPerson.age);};NSLog(@"---------------");}return 0;
}

使用__unsafe_unretained也可以正常释放

__unsafe_unretained从命名看,unsafe代表不安全,unretained表示不会产生引用。不安全则表现在,当引用的对象销毁时,他不会把指针设置为nil,因此容易有坏指针异常

3.3 __block

int main(int argc, const char * argv[]) {@autoreleasepool {ZSXPerson *person = [[ZSXPerson alloc] init];person.age = 10;__block typeof(person) strongPerson = person;person.block = ^ {NSLog(@"person.age is %d", strongPerson.age);strongPerson = nil;};person.block();NSLog(@"---------------");}return 0;
}


使用__block正常销毁

需要注意的是,使用__block必须调用block。因为使用__block修饰后,在block里面需要置空,如果没有调用block,就没有置空操作,它依然是循环引用状态无法销毁

未调用block:

调用block后:

4. MRC下

MRC不支持__weak
改为MRC

4.1 __unsafe_unretain…

int main(int argc, const char * argv[]) {@autoreleasepool {ZSXPerson *person = [[ZSXPerson alloc] init];person.age = 10;__unsafe_unretained typeof(person) weakPerson = person;person.block = [^ {NSLog(@"person.age is %d", weakPerson.age);} copy];NSLog(@"---------------");[person release];}return 0;
}

正常销毁

4.1 __block

int main(int argc, const char * argv[]) {@autoreleasepool {ZSXPerson *person = [[ZSXPerson alloc] init];person.age = 10;__block typeof(person) weakPerson = person;person.block = [^ {NSLog(@"person.age is %d", weakPerson.age);} copy];NSLog(@"---------------");[person release];}return 0;
}

正常销毁

MRC下,block 里面无需将weakPerson设置为nil,也能正常释放。这是因为,MRC__block不会对person产生强引用(被__block修饰的对象类型,ARC时会retain,MRC时不会retain)

相当于这根线不生效,因此没有形成循环引用

5. 总结

5.1 ARC下

通常使用__weak来解决循环引用。使用__weak修饰的对象销毁后,指针会自动设置为nil__unsafe_unretained__block虽然也可以解决环引用问题,但是__unsafe_unretained在修饰的对象销毁后,指针不会自动设置为nil,因此如果还去使用这个对象就会出现异常。__block需要保证 block 有被调用,否则还是会循环引用。

5.2 MRC下

使用__unsafe_unretained或者__block

@oubijiexi

相关文章:

OC对象 - Block解决循环引用

文章目录 OC对象 - Block解决循环引用前言1. 循环引用示例1.1 分析 2. 解决思路3. ARC下3.1 __weak3.2 __unsafe_unretained3.3 __block 4. MRC下4.1 __unsafe_unretain....4.1 __block 5. 总结5.1 ARC下5.2 MRC下 OC对象 - Block解决循环引用 前言 本章将会通过一个循环引用…...

Java设计模式之装饰器模式

装饰器模式是一种结构型设计模式,它允许动态地将责任附加到对象上。装饰器模式是通过创建一个包装对象,也就是装饰器,来包裹真实对象,从而实现对真实对象的功能增强。装饰器模式可以在不修改原有对象的情况下,动态地添…...

Java基础知识总结(25)

代理模式 什么是代理模式? 代理模式是指,为其他对象提供一种代理以控制这个对象的访问。一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户和目标对象之间起到中介的作用。换句话说,代理模式,是在不修…...

Vue3 实现基于token 用户登录

前后端分离情况下,实现的大致思路 1 第一次登录的时候,前端调用后端的登录接口,发送用户名与密码 2 后端收到请求,验证用户名和密码,验证成功 给前端返回一个token 3 前段拿到token 将token 存储进localStorage 和…...

在word中显示Euclid Math One公式的问题及解决(latex公式,无需插件)

问题:想要在word中显示形如latex中的花体字母 网上大多解决办法是安装Euclid Math One。安装后发现单独的符号插入可行,但是公式中选择该字体时依然显示默认字体。 解决办法:插入公式后,勾选左上角的latex 在公式块中键入latex代码…...

江协科技STM32:按键控制LED光敏传感器控制蜂鸣器

按键控制LED LED模块 左上角PA0用上拉输入模式,如果此时引脚悬空,PA0就是高电平,这种方式下,按下按键,引脚为低电平,松下按键,引脚为高电平 右上角PA0,把上拉电阻想象成弹簧 当按键…...

最佳矢量绘图设计软件Sketch for Mac v99.5 最新中文激活版

Sketch for Mac是一款功能强大的矢量绘图软件,它提供了简单易用的界面和丰富的工具,让用户能够轻松创建精美的设计作品。 软件下载:Sketch for Mac v99.5 最新中文激活版 Sketch具有直观的布局和智能的工具,使得设计师能够快速实现…...

【IntelliJ IDEA】运行测试报错解决方案(附图)

IntelliJ IDEA 版本 2023.3.4 (Ultimate Edition) 测试报错信息 命令行过长。 通过 JAR 清单或通过类路径文件缩短命令行,然后重新运行 解决方案 修改运行配置,里面如果没有缩短命令行,需要再修改选项里面勾选缩短命令行让其显示&#x…...

【Kotlin】List、Set、Map简介

1 List Java 的 List、Set、Map 介绍见 → Java容器及其常用方法汇总。 1.1 创建 List 1.1.1 emptyList var list emptyList<String>() // 创建空List 1.1.2 List 构造函数 var list1 List(3) { "abc" } // [abc, abc, abc] var list2 ArrayList<In…...

OpenCV 形态学处理函数

四、形态学处理&#xff08;膨胀&#xff0c;腐蚀&#xff0c;开闭运算&#xff09;_getstructuringelement()函数作用-CSDN博客 数字图像处理(c opencv)&#xff1a;形态学图像处理-morphologyEx函数实现腐蚀膨胀、开闭运算、击中-击不中变换、形态学梯度、顶帽黑帽变换 - 知乎…...

互联网摸鱼日报(2024-03-27)

互联网摸鱼日报(2024-03-27) 36氪新闻 谈“肉”色变&#xff0c;预制菜“顶流”要完&#xff1f; 欧美监管机构出重拳&#xff0c;苹果和谷歌都要被拆分了吗&#xff1f; 为什么产品经理的薪资待遇&#xff0c;这么高&#xff1f; AI PC&#xff1a;一场浩荡的革命 二氧化…...

2014年认证杯SPSSPRO杯数学建模B题(第二阶段)位图的处理算法全过程文档及程序

2014年认证杯SPSSPRO杯数学建模 B题 位图的处理算法 原题再现&#xff1a; 图形&#xff08;或图像&#xff09;在计算机里主要有两种存储和表示方法。矢量图是使用点、直线或多边形等基于数学方程的几何对象来描述图形&#xff0c;位图则使用像素来描述图像。一般来说&#…...

C++基本语法

C是如何工作的 文章目录 C是如何工作的1、新建Hello World工程1.1使用Visual Studio新建项目1.2 HelloWorld1.2.1 命名空间1.2.2 输出输出 1.3 注释1.4 函数1.4.1 使用有返回的函数1.4.2 自定义函数 1、新建Hello World工程 1.1使用Visual Studio新建项目 按照下面的图片&…...

Node Sass does not yet support your current environment

项目运行时报错&#xff1a;Node Sass does not yet support your current environment 原因是node版本过高。 解决办法&#xff1a; 使用nvm管理node版本&#xff0c;&#xff08;如何安装nvm&#xff1f;请点击跳转&#xff09; 具体步骤如下&#xff1a; 1.查看当前node…...

长陆工业自动控制系统邀您到场参观2024第13届生物发酵产品与技术装备展

参展企业介绍 珠海市长陆工业自动控制系统股份有限公司于2004年在素有“百岛之市&#xff0c;浪漫之城”的珠江口西岸核心城市—珠海成立。长陆工业是流程工业智能制造自动化、信息化综合解决方案的提供者。产品遍及冶金、化工、建材、食品、石油、橡塑、能源、环保、物流、粮…...

数据仓库——维度表更新

维度表的更新 维度表修改规律: 绝大部分维度表都是不变的很多维度虽然会变化&#xff0c;但是变化的很缓慢源记录产品键不会改变产品描述及其他属性的改变都很缓慢在源OLTP 系统中&#xff0c;新的值会覆盖旧的值在数据仓库中&#xff0c;覆盖维度表的属性并不总是适当的做法…...

Web3创作整理 - 2024-02-23 ~ 2024-03-25

Web3 创作整理 - 2024-02-23 ~ 2024-03-25 整理下3月份的文章&#xff0c;方便大家阅读 分类文章地址&#x1fad1;ETH什么是Dapp&#x1f3bc;ETH什么是以太坊&#x1f3b5;ETH如何才能拥有ETH&#x1f3b6;ETHBTC网络 vs ETH网络&#x1f399;️ETHETH网络中的区块链&#x1…...

CSS(一)---【CSS简介、导入方式、八种选择器、优先级】

零.前言 本系列适用于零基础小白&#xff0c;亦或是初级前端工程师提升使用。 知识点较为详细&#xff0c;如果追求非常详细&#xff0c;请移步官方网站或搬运网站。 1.CSS简介 CSS全称&#xff1a;“Cascading Style Sheets”&#xff0c;中文名&#xff1a;“层叠样式表”…...

智慧公厕解决方案打造更加智能的卫生空间

一、智慧公厕方案概述 智慧公厕方案旨在解决现有公厕存在的诸多问题&#xff0c;包括民众用厕困难、环境卫生状况不佳、管理效率低下等方面。针对民众的需求和管理方面的挑战&#xff0c;智慧公厕提供了一套综合解决方案&#xff0c;包括智能导航、环境监测、资源管理等功能&a…...

美团0316春招笔试题

下面是美团2024-03-16笔试真题&#xff0c;进行了VP&#xff0c;由于未参与评测&#xff0c;故不保证正确性&#xff0c;仅供参考。 第一题 小美点外卖 求和然后减去满减和红包即可。 #include <bits/stdc.h> using namespace std; using LL long long ; int n, t, x,…...

云计算——弹性云计算器(ECS)

弹性云服务器&#xff1a;ECS 概述 云计算重构了ICT系统&#xff0c;云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台&#xff0c;包含如下主要概念。 ECS&#xff08;Elastic Cloud Server&#xff09;&#xff1a;即弹性云服务器&#xff0c;是云计算…...

【OSG学习笔记】Day 18: 碰撞检测与物理交互

物理引擎&#xff08;Physics Engine&#xff09; 物理引擎 是一种通过计算机模拟物理规律&#xff08;如力学、碰撞、重力、流体动力学等&#xff09;的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互&#xff0c;广泛应用于 游戏开发、动画制作、虚…...

数据链路层的主要功能是什么

数据链路层&#xff08;OSI模型第2层&#xff09;的核心功能是在相邻网络节点&#xff08;如交换机、主机&#xff09;间提供可靠的数据帧传输服务&#xff0c;主要职责包括&#xff1a; &#x1f511; 核心功能详解&#xff1a; 帧封装与解封装 封装&#xff1a; 将网络层下发…...

sqlserver 根据指定字符 解析拼接字符串

DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...

前端开发面试题总结-JavaScript篇(一)

文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包&#xff08;Closure&#xff09;&#xff1f;闭包有什么应用场景和潜在问题&#xff1f;2.解释 JavaScript 的作用域链&#xff08;Scope Chain&#xff09; 二、原型与继承3.原型链是什么&#xff1f;如何实现继承&a…...

自然语言处理——Transformer

自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效&#xff0c;它能挖掘数据中的时序信息以及语义信息&#xff0c;但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN&#xff0c;但是…...

汇编常见指令

汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX&#xff08;不访问内存&#xff09;XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...

IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)

文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...

如何理解 IP 数据报中的 TTL?

目录 前言理解 前言 面试灵魂一问&#xff1a;说说对 IP 数据报中 TTL 的理解&#xff1f;我们都知道&#xff0c;IP 数据报由首部和数据两部分组成&#xff0c;首部又分为两部分&#xff1a;固定部分和可变部分&#xff0c;共占 20 字节&#xff0c;而即将讨论的 TTL 就位于首…...

.Net Framework 4/C# 关键字(非常用,持续更新...)

一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...