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.mfbz.cn/a/496349.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

深入解析RSA算法原理及其安全性机制

码到三十五 : 个人主页 心中有诗画,指尖舞代码,目光览世界,步履越千山,人间尽值得 ! 目录 一、RSA算法简介二、RSA算法原理2.1 背景与数学基础2.2 密钥生成2.3 加密过程2.4 解密过程 三、安全性考虑四、RSA的使用五、…

P2602 [ZJOI2010] 数字计数

经典计数问题&#xff0c;注意0的判断 所以要引入前导0标记 #include<bits/stdc.h> using namespace std; using ll long long; using pii pair<int,int>; #define int long long const int N 1e510; const int inf 0x3f3f3f3f; const int mod 1e97; int gcd(…

华为OD机试 - 考古问题 - 回溯、全排列问题(Java 2024 C卷 200分)

华为OD机试 2024C卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;A卷B卷C卷&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;每一题都有详细的答题思路、详细的代码注释、样例测试…

自动化测试:Selenium中的时间等待

在 Selenium 中&#xff0c;时间等待指在测试用例中等待某个操作完成或某个事件发生的时间。Selenium 中提供了多种方式来进行时间等待&#xff0c;包括使用 ExpectedConditions 中的 presence_of_element_located 和 visibility_of_element_located 方法等待元素可见或不可见&…

StartAI修图实例教程之海报修图

发现AI的另一种用法——AI修图。想必许多电商小伙伴都会遇到海报修图问题&#xff0c;今天我们就来看看怎么处理&#xff01; 原图&#xff1a; 1.我们用PS自带的魔法棒工具进行选区&#xff0c;选择海报中需要修改的区域。我们今天是已“2024”两个字为例 效果图&#xff1…

每日必学Linux命令:cd命令

1.命令格式&#xff1a; cd [目录名]2.命令功能 切换当前目录至 [目录名]3. 常用范例 1.进入系统根目录 命令&#xff1a; cd / 说明&#xff1a;进入系统根目录,上面命令执行完后拿ls命令看一下&#xff0c;当前目录已经到系统根目录了 输出&#xff1a; hchc-virtu…

【YOLOv5改进系列(5)】高效涨点----添加密集小目标检测NWD方法

文章目录 &#x1f680;&#x1f680;&#x1f680;前言一、1️⃣ 修改loss.py文件1.1 &#x1f393; 修改11.2 ✨ 修改21.3 ⭐️相关代码的解释 二、2️⃣NWD实验2.1 &#x1f393; 实验一&#xff1a;基准模型2.2 ✨实验二&#xff1a;NWD权重设置0.52.3 ⭐️实验三&#xf…

开了抖店还不知道怎么下手操作的,建议把这篇文章看完!

大家好&#xff0c;我是电商小布。 我们都知道&#xff0c;抖音这个平台可以说是当前短视频行业中&#xff0c;最主流的项目了。 而这其中发展的电商&#xff0c;也是逐渐成为了行业内的头部。 对于一些想要在其中享受到优势的小伙伴&#xff0c;就抓住这个机会&#xff0c;…

基于Java仓库管理系统设计与实现(源码+部署文档+论文)

博主介绍&#xff1a; ✌至今服务客户已经1000、专注于Java技术领域、项目定制、技术答疑、开发工具、毕业项目实战 ✌ &#x1f345; 文末获取源码联系 &#x1f345; &#x1f447;&#x1f3fb; 精彩专栏 推荐订阅 &#x1f447;&#x1f3fb; 不然下次找不到 Java项目精品实…

无服务数据库是未来的趋势吗?

无服务数据库是未来的趋势吗&#xff1f; 无服务器数据库是未来的趋势吗&#xff1f;无服务器数据库与传统云数据库有何不同&#xff1f; Amazon Aurora Serverless&#xff08;如下图所示&#xff09;是 Amazon Aurora 的一种配置方式&#xff0c;可以按需自动扩展。 Aurora…

ChatGPT 商业金矿(上)

原文&#xff1a;ChatGPT Business Goldmines 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 第一章&#xff1a;为什么我写这本书 欢迎阅读《ChatGPT 多源收入&#xff1a;20 个利润丰厚的业务&#xff0c;任何人都可以在一周内使用 ChatGPT 开始》。我很高兴分享我…

谷歌上架,账号高风险被封,一定是账号问题吗?

最近&#xff0c;很多开发者反馈&#xff0c;开发者账号总是被谷歌官方以“高风险行为”封号。封号邮件如图&#xff1a; 我们都清楚&#xff0c;账号被封的主要原因无非是账号本身质量问题和程序代码的问题。但目前大多数开发者普遍认为&#xff0c;如果账号是因为“高风险”被…

m4r是什么文件格式?用什么软件打开?

m4r文件格式的诞生伴随着移动设备智能化的崛起。这个格式最初是苹果公司为其iPhone设计的一种特殊的铃声格式。在这个数字音频领域&#xff0c;用户对于个性化铃声的需求逐渐升温&#xff0c;m4r文件格式因此迎来了时代的机遇。这个独特的音频格式的产生&#xff0c;旨在为用户…

UE RPC 外网联机(1)

技术&#xff1a;RPC TCP通信 设计&#xff1a;大厅服务<---TCP--->房间服务<---RPC--->客户端&#xff08;Creator / Participator&#xff09; 1. PlayerController 用于RPC通信控制 2.GameMode 用于数据同步 3.类图 4. 注意 &#xff08;1&#xff09;RPC&a…

Advisor 被重复代理问题排查

问题场景 项目中存在多个 AbstractAdvisorAutoProxyCreator 且其持有的 Advisor Bean 重复 问题复现 相关代码 ResponseBodyRequiresPermissions(PermissionConstant.****)GetMapping(value "/query****.json", name "")public List<***> query…

处理 Oracle 数据库表空间满的问题

处理 Oracle 数据库表空间满的问题 1、诊断表空间满的问题2、处理表空间满的问题3、设置表空间自增结论 在 Oracle 数据库管理中&#xff0c;表空间是一个重要的概念&#xff0c;用于存储数据库对象和数据。当表空间满了时&#xff0c;可能会导致数据库的运行受到影响&#xff…

计算机网络知识

第一章 局域网广播技术&#xff1b;广域网交换技术 n-SDUn-PCIn-PDU TCP/IP网络层无连接&#xff0c;传输层有链接和无连接&#xff1b;OSI传输层有链接和无连接&#xff0c;网络层有链接 TCP/IP没有明确区分服务&#xff0c;接口&#xff0c;协议&#xff0c;OSI明确区分 OSI…

实验7 内置对象response

编写代码&#xff0c;掌握request、response的用法。【参考课本4.6.2】 三、源代码以及执行结果截图&#xff1a; input.jsp <% page language"java" contentType"text/html; charsetutf-8" pageEncoding"utf-8"%> <!DOCTYPE html>…

微信小程序开发之常用组件解释

1 基础内容组件 1.1text组件 text的功能主要是用于内联文本&#xff0c;与网页中的span有点类似。 主要属性有 例子&#xff1a;页面上添加一个可以选中的文本 在wxml文件中添加&#xff1a; <view> <text user-select>17544456565</text> </view>…

ReentrantLock 原理

(一)、非公平锁实现原理 1、加锁解锁流程 先从构造器开始看&#xff0c;默认为非公平锁实现 public ReentrantLock() {sync new NonfairSync(); } NonfairSync 继承自 AQS 没有竞争时 加锁流程 构造器构造&#xff0c;默认构造非公平锁(无竞争&#xff0c;第一个线程尝试…
最新文章