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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/770686.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

flask_restful的基本使用

优势: Flask-Restful 是一个专门用来写 restful api 的一个插件。 使用它可以快速的集成restful api 接口功能。 在系统的纯api 的后台中,这个插件可以帮助我们节省很多时间。 缺点: 如果在普通的网站中,这个插件就没有优势了&…

测试环境搭建整套大数据系统(十二:挂载磁盘到hadoop环境)

一:链接硬盘 将硬盘连接到计算机的 SATA 接口或 USB 接口,并确保硬盘通电并处于可用状态。 二:查看硬盘信息 sudo fdisk -l三:创建分区 gdisk /dev/vbd重新扫描磁盘 partprobe /dev/vdb格式化磁盘 mkfs.ext4 /dev/vdb2查看磁…

前端学习之css基本网格布局

网格布局 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>网格布局</title><style>.a{/* grid网格布局 */display: grid;width: 400px;height: 400px;border: 1px solid red;/* 设置当前…

iOS开发之SwiftUI

iOS开发之SwiftUI 在iOS开发中SwiftUI与Objective-C和Swift不同&#xff0c;它采用了声明式语法&#xff0c;相对而言SwiftUI声明式语法简化了界面开发过程&#xff0c;减少了代码量。 由于SwiftUI是Apple推出的界面开发框架&#xff0c;从iOS13开始引入&#xff0c;Apple使用…

我在京东做数据分析,一位京东数据分析师的工作日常

有人说&#xff1a;“种下一棵树最好的时间是十年前&#xff0c;其次是现在”。任何时候&#xff0c;我们都应该抓住机遇&#xff0c;说不定就是改变你现状的一个机会。 2020年&#xff0c;我在疫情得到控制后&#xff0c;面试入职京东大数据组&#xff0c;截止目前&#xff0…

获取高德安全码SHA1

高德开发者平台上给的三种方法 获取安全码SHA1&#xff0c;这里我自己使用的是第三种方法。 1、通过Eclipse编译器获取SHA1 使用 adt 22 以上版本&#xff0c;可以在 eclipse 中直接查看。 Windows&#xff1a;依次在 eclipse 中打开 Window -> Preferances -> Androi…

flask_restful结合蓝图使用

在蓝图中&#xff0c;如果使用 Flask_RESTful &#xff0c; 创建 Api 对象的时候&#xff0c;传入蓝图对象即可&#xff0c;不再是传入 app 对象 /user/__init__.py from flask.blueprints import Blueprintuser_bp Blueprint(user,__name__)from user import views /user…

word文件如何转PDF格式?word转PDF的方法

在当今数字化时代&#xff0c;文档格式的转换已成为日常生活和工作中不可或缺的一部分。其中&#xff0c;将Word文档转换为PDF格式更是受到了广大用户的青睐。本文将详细介绍Word转PDF的方法&#xff0c;帮助读者轻松实现文档格式的转换&#xff0c;并探讨转换过程中的注意事项…

工业互联网下的增强现实

工业互联网下的增强现实 1、 概述 增强现实&#xff08;Augmented Reality&#xff0c;简称AR&#xff09;&#xff0c;增强现实技术也被称为扩增现实&#xff0c;AR增强现实技术是促使真实世界信息和虚拟世界信息内容之间综合在一起的较新的技术内容&#xff0c;其将原本在现…

【浅尝C++】类和对象第二弹=>类的6个默认成员函数/运算符重载详谈

&#x1f3e0;专栏介绍&#xff1a;浅尝C专栏是用于记录C语法基础、STL及内存剖析等。 &#x1f6a9;一些备注&#xff1a;之前的文章有点杂乱&#xff0c;这里将前面的知识点重新组织了&#xff0c;避免了过多冗余的废话。 &#x1f3af;每日努力一点点&#xff0c;技术变化看…

Appium Inspector 展示设备当前页面

定位元素需要使用appium inspector&#xff0c;之前每次都是从登录页开始&#xff0c;后来发现连接设备的时候只需要去掉appPackage、appActivity即可。 { "platformName": "Android", "platformVersion": "6", "deviceNa…

35.网络游戏逆向分析与漏洞攻防-游戏网络通信数据解析-登录成功数据包内容分析

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 如果看不懂、不知道现在做的什么&#xff0c;那就跟着做完看效果 内容参考于&#xff1a;易道云信息技术研究院VIP课 上一个内容&#xff1a;34.登录数据包的…

LGBM算法 原理

简介 GBDT (Gradient Boosting Decision Tree) 是机器学习中一个长盛不衰的模型&#xff0c;其主要思想是利用弱分类器&#xff08;决策树&#xff09;迭代训练以得到最优模型&#xff0c;该模型具有训练效果好、不易过拟合等优点。GBDT不仅在工业界应用广泛&#xff0c;通常被…

伪装目标检测之注意力CBAM:《Convolutional Block Attention Module》

论文地址&#xff1a;link 代码&#xff1a;link 摘要 我们提出了卷积块注意力模块&#xff08;CBAM&#xff09;&#xff0c;这是一种简单而有效的用于前馈卷积神经网络的注意力模块。给定一个中间特征图&#xff0c;我们的模块依次推断沿着两个独立维度的注意力图&#xff…

10.2024

使用选择排序将{2,9,5,0,1,3,6,8}排序 代码&#xff1a; public class 第十题 {public static void main(String[] args) {int a[]{2,9,5,0,1,3,6,8};int begin0;int enda.length-1;while (begin<end){int mina[begin];int tbegin;for (int ibegin;i<end;i){if(min>…

Selenium 自动化 —— 定位页面元素

更多内容请关注我的 Selenium 自动化 专栏&#xff1a; 入门和 Hello World 实例使用WebDriverManager自动下载驱动Selenium IDE录制、回放、导出Java源码浏览器窗口操作切换浏览器窗口 使用 Selenium 做自动化&#xff0c;我们不仅仅是打开一个网页&#xff0c;这只是万里长…

Python私有属性和私有方法

私有属性和私有方法 在实际开发中&#xff0c;对象的某些属性或者方法只希望在对象内部被使用&#xff0c;而不希望在外界被访问。 私有属性&#xff1a;对象不希望公开的属性 私有方法&#xff1a;对象不希望公开的方法 定义方式&#xff1a;在属性名或者方法名前添加两个下划…

flask_restful规范返回值之类型设置

大型的互联网项目中&#xff0c;返回的数据格式&#xff0c;有时是比较复杂的结构。 如&#xff1a;豆瓣电影 https://movie.douban.com/j/chart/top_list?type24&interval_id 100%3A90&action&start20&limit20 返回的值里有 json 或者列表数据&#xff0c…

解决sqlalchemy执行语句提示Not an executable object

问题&#xff1a; from sqlalchemy import create_engine# 数据库的变量 HOST 127.0.0.1 PORT 3306 DATA_BASE itbz USERroot PWD123456 # DB_URL f数据库的名驱动名://{USER}:{PWD}{HOST}:{PORT}/{DATA_BASE} DB_URL fmysqlpymysql://{USER}:{PWD}{HOST}:{PORT}/{DATA_B…

分类模型评估:混淆矩阵与ROC曲线

1.混淆矩阵2.ROC曲线 & AUC指标 理解混淆矩阵和ROC曲线之前&#xff0c;先区分几个概念。对于分类问题&#xff0c;不论是多分类还是二分类&#xff0c;对于某个关注类来说&#xff0c;都可以看成是二分类问题&#xff0c;当前的这个关注类为正类&#xff0c;所有其他非关注…