【iOS】NSError**和__autoreleasing场景

news2025/2/27 11:22:32

前言

在看JSONModel源码的时候,JSONModel的自定义Error的方法一直在报错

- (BOOL)validate:(NSError *__autoreleasing *)error {
    
}

这个方法在定义error的时候添加上了__autoreleasing修饰符,涉及到了__autoleasing的显式隐式调用就去了解了一下。

发现在ARC的时候对这个修饰符学习的很浅,这里复习➕学习。

在这之前还是了解__autoreleasing修饰符的作用和原理

autoreleasing 在MRC和ARC下的应用

__autoreleasing 是一个用于 ARC(自动引用计数)的关键字,它可以在方法返回对象时自动将对象加入到 autorelease pool 中。

在ARC里,如果一个方法返回一个对象,编译器会自动生成一个 __autoreleasing 变量,并将这个对象赋值给这个变量,然后将这个变量加入到 autorelease pool 中,以便在 pool 被 drain 时释放对象。

在手动管理内存的 MRC 环境中,如果想要将一个对象加入到 autorelease pool 中,可以显式地使用 NSAutoreleasePool 的 addObject: 方法将对象添加到 pool 中,或者使用 autorelease 方法将对象加入到当前 autorelease pool 中。

使用 __autoreleasing 关键字的隐式调用是在方法返回对象时自动完成的,而显式调用是在需要手动将对象添加到 autorelease pool 中时使用的。

__autoreleasing如何做到延迟释放

顺带提一下 在定义 Objective-C 的 @property 时,不能使用 __autoreleasing 修饰符,因为该修饰符只适用于手动内存管理的情况,而在 ARC 中,对象的内存管理已经由编译器自动处理,不需要手动管理

__autoreleasing是可以延迟释放对象,在ARC里,__weak修饰的对象在声明周期结束的时候就会自动释放掉,那么就利用_autoreleasing修饰符演示如何延迟释放

#import "ViewController.h"

@interface ViewController ()
@property (nonatomic,weak) NSObject *weakObj1;
@property (nonatomic,weak) NSObject *weakObj2;
@end

@implementation ViewController
- (void)test {
     NSLog(@"--1---%@--%@",self.weakObj1,self.weakObj2);
     [self test2];
     NSLog(@"--3---%@--%@",self.weakObj1,self.weakObj2);
 }
- (void)test2 {
     __autoreleasing NSObject *obj1 = [NSObject new];
     NSObject *obj2 = [NSObject new];
     self.weakObj1 = obj1;
     self.weakObj2 = obj2;
     NSLog(@"--2---%@--%@",self.weakObj1,self.weakObj2);
 }
- (void)viewDidLoad {
    [super viewDidLoad];
    [self test];
    // Do any additional setup after loading the view.
}


@end

请添加图片描述
对于打印1,对象还没有初始化 为NULL

对于打印2,对象在test2属性持有了obj1,obj2变量, obj1使用了__autoreleasing

对于打印3, weakObj1和weakObj2都是使用weak修饰符,但是在test2里面对obj1使用了__autoreleasing修饰符,所以obj1会超出自己的作用地域而存在,但是obj2么有使用延迟销毁修饰符。

汇编看看

针对obj1和obj2的初始化

- (void)howDelate {
    __autoreleasing NSObject *obj1 = [NSObject new];
    NSObject *obj2 = [NSObject new];
}

请添加图片描述

- (void)howDelate伪代码{

   // __autoreleasing NSObject *obj1 = [NSObject new]; 等同于:
    id obj1 = objc_msgSend(NSObject, @selector(new));
    objc_autorelease(obj1);

   // NSObject *obj2 = [NSObject new]; 等同于:
    id obj2 = objc_msgSend(NSObject, @selector(new));
    defer {
       objc_storeStrong(&obj2,nil)
    }
}

 void objc_storeStrong(id *location, id obj) {
    id prev = *location;
    if (obj == prev) {
        return;
    }
    objc_retain(obj);
    *location = obj;
    objc_release(prev);
}

obj1 在被__autoreleasing修饰后被加入至自动缓存池,并且在函数结束时不会再调用objc_storeStrong,因此摆脱函数作用域对它的生命周期的影响。

显式和隐式的调用__autoreleasing

其实在上述的obj1 已经显示的调用了__autoreleasing

  __autoreleasing NSObject *obj1 = [NSObject new];

隐式使用__autoreleasing的情况就是你的代码上看不到它,但是它编译后确实会存在,

//这个是我们的TestObj的创建对象的一个自定义类方法
+ (TestObj *)obj
{
  /*
    本来这个对象创建出来默认是__strong的,
    但是因为编译器发现这个对象是要被当做返回值返回出去的,
    所以不能在这个方法结束时候就release这个对象,
    而应该放长远的眼光,使用autorelease,这个其实也是在MRC里
  */
  TestObj * obj = [[TestObj alloc] init];
  return obj;
}

NSError**与autoreleasing的关系

再次回到刚开始的问题,这两个东西看似没什么关系,其实大有联系**。他们俩是绑定关系**

为什么呢?

先介绍NSError**

NSError** 是指向一个 NSError 对象指针的指针,通常用于在方法中传递错误信息。使用这种方式传递错误信息的原因是如果在方法执行过程中发生错误,方法本身可能无法处理该错误,因此需要将错误信息返回给调用方以供处理

什么是指向对象指针的指针?

指向对象指针的指针是指一个指针变量,它存储的是另一个指针变量的地址,而这个指针变量指向的是一个对象请添加图片描述

为什么NSError需要__autoreleasing的帮助?

在方法中将 NSError 对象传递给调用方时,通常需要使用 __autoreleasing 修饰符,以确保错误对象能够被正确地释放。具体来说,如果不使用 __autoreleasing 修饰符,那么在方法返回时,该对象可能被自动释放池回收,导致调用方得到的错误对象是一个悬垂指针,无法正常使用。因此,在将 NSError 对象传递给调用方时,通常使用以下方式定义:

- (BOOL)doSomethingWithError:(NSError * __autoreleasing *)error;

这样,调用方传递一个指向 NSError 指针的指针,方法在执行过程中需要修改该指针指向的对象时,使用 *error 进行操作。在方法返回时,自动释放池会自动管理 NSError 对象的释放,无需手动释放。

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

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

相关文章

【C++ 三】一维数组、二维数组

数组概述、一维数组、二维数组 文章目录数组概述、一维数组、二维数组前言1 数组1.1 概述2 一维数组2.1 一维数组定义方式2.2 一维数组数组名2.3 冒泡排序3 二维数组3.1 二维数组定义方式3.2 二维数组数组名总结前言 本文包含数组概述、一维数组、二维数组。 1 数组 1.1 概述…

python web 医院加密处方系统

医院加密处方系统 环境要求: 1、python3.8 2、vue 3、django 4、mysql 5、ruoyi快速开发框架 登录界面 可以登录和注册,注册分三个角色,主治医师和药品医师还有配制医师,有验证码和用户权限功能,用户管理、部…

AIGC下一站:期待、警惕充斥着AI剪辑师的世界

上月底,名为“chaindrop”的 Reddit 用户,在 r/StableDiffusion subreddit 上分享了一个由人工智能生成的视频,在业内引起了不小的争议。 视频中,一个由 AI 生成的丑陋畸形的 “威尔史密斯”,以一种可怕的热情将一把意…

vba:消息框基础,massagebox

常量常量值说明vbOKOnly0只显示“确定”按钮(缺省值)VbOKCancel1显示“确定”和“取消”按钮VbAbortRetryIgnore2显示“终止”、“重试”和“忽略” 按钮VbYesNoCancel3显示“是”、“否”和“取消”按钮VbYesNo4显示“是”和“否”按钮VbRetryCancel5显…

pkg-config

前言 在介绍 pkg-config 之前&#xff0c;先讲一个我的经历。 有一次我想用 libgtk 库在 ubuntu 上实现一个简单的图形界面&#xff0c;就像下面代码 #include <gtk/gtk.h>int main(int argc, char *argv[]) {GtkWidget *window;gtk_init(&argc, &argv);window…

UG NX二次开发(C#)-建模-获取曲面的法矢

文章目录 1、前言2、曲面的法矢示例3、获取曲面的法矢3.1 采用 uFModl.AskFaceProps实现3.2采用 uFSo实现4、结论1、前言 在UG NX二次开发过程中,我们想获取曲面的法矢,是通过ufun函数来获取的。我们以一个平面和一个曲面来说明其开发过程。 2、曲面的法矢示例 创建一张曲…

商城系统开发方案分析

互联网的不断发展&#xff0c;电商行业已经成为了当前最重要的商业形式之一。商城系统的开发也因此而备受关注。商城系统的开发是针对B2C、B2B2C等多种商业模式&#xff0c;如用户熟知的SHOP、商派等一系列商城系统&#xff0c;将商品和服务进行在线销售的一个综合性平台。那么…

【软考备战·希赛网每日一练】2023年4月17日

文章目录一、今日成绩二、错题总结第一题第二题第三题第四题三、知识查缺题目及解析来源&#xff1a;2023年04月17日软件设计师每日一练 一、今日成绩 二、错题总结 第一题 解析&#xff1a; 第二题 解析&#xff1a; 第三题 解析&#xff1a; SCAN调度算法 也叫 “电梯”算…

RocketMQ 发送批量消息、过滤消息和事务消息

前面我们知道RocketMQ 发送延时消息与顺序消息&#xff0c;现在我们看下怎么发送批量消息、过滤消息和事务消息。 发送批量消息 限制是这些批量消息应该有相同的 topic&#xff0c;相同的 waitStoreMsgOK&#xff0c;而且不能是延时消息。 此外&#xff0c;这一批消息的总大小…

如何合理选择ClickHouse表主键

ClickHouse提供索引和数据存储的复杂机制&#xff0c;能够实现在高负载下仍有优异的读写性能。当创建MergeTree表时需要选择主键&#xff0c;主键影响大多数查询性能。本文介绍主键的工作原理&#xff0c;让我们知道如何选择合适的主键。 设置主键 MergeTree表可以设置主键&am…

香橙派5使用RK3588S内置NPU加速yolov5推理,实时识别数字达到50fps

前言&#xff1a; 香橙派5采用了RK3588S&#xff0c;内置的NPU达到了6Tops的算力&#xff0c;博主这里记录一下自己的踩坑过程&#xff0c;好不容易做出来的不能以后忘记了&#xff08;手动狗头&#xff09;。这里博主还在B站上发布了效果视频&#xff0c;大家感兴趣的话可以看…

TensorFlow 和 Keras 应用开发入门:1~4 全

原文&#xff1a;Beginning Application Development with TensorFlow and Keras 协议&#xff1a;CC BY-NC-SA 4.0 译者&#xff1a;飞龙 本文来自【ApacheCN 深度学习 译文集】&#xff0c;采用译后编辑&#xff08;MTPE&#xff09;流程来尽可能提升效率。 不要担心自己的形…

Java 中的 非并发容器

1.四大类容器 java中容器主要有四大类&#xff0c;如下图所示 2.非并发容器 1) List 类 List 类 不支持并发的有 ArrayList 与 LinkedList ArrayList 底层实现 ArrayList 底层为 数组&#xff0c;由于数组的特性&#xff0c;非常适合用于 查询多&#xff0c;增删改的业务…

【数据结构学习1】数据结构

目录数据结构定义数据结构的构成逻辑结构逻辑结构的类型存储结构数据运算数据类型和抽象数据类型算法定义分析基础时间复杂度分析事前分析估算法 -> 分析算法的执行时间时间复杂度时间复杂度类型简化的算法时间复杂度分析空间复杂度分析数据结构 定义 数据&#xff1a;所有…

工作流调度系统 Azkaban介绍与安装(一)

文章目录前言1、为什么要用工作流调度系统2、常见的工作流调度系统1 集群规划2 配置 MySQL3 配置 Executor Server3.1 修改 azkaban.properties3.2 启动3.3 激活4 配置 Web Server4.1 修改 azkaban.properties4.2 修改azkaban-users.xml文件&#xff0c;添加 atguigu 用户4.3 启…

VM 虚拟机没有网络,无法Ping通

场景&#xff1a; 虚拟机用过&#xff0c;之前一切正常&#xff0c;使用NAT模式联网&#xff0c;配置了静态IP换了路由器&#xff0c;推测是主机IP网段变了无法使用ssh工具连接虚拟机&#xff0c;且相互都ping不通&#xff08;后来经历了主机可以ping通虚拟机&#xff0c;虚拟…

PWM寄存器初始化

本模块主要实现输出频率占空比可调的 PWM 波形功能和输入捕获功能&#xff0c;同时也可作为计数器使用。一、主要特性 1. 16位向上或向下计数器&#xff1b; 2. 支持最多6路PWM通道&#xff1b; 3. 每个通道支持输出比较或边缘对齐PWM模式波形输出&#xff0c;支持设置、清除、…

关于 CSDN-AI 机器人 programmer_ada —— 阿达·洛夫莱斯(Ada Lovelace)

收到早期文章的一条新评论&#xff1a; 文笔和内容稍稍透漏着机器人的风格&#xff0c;打开主页果不其然 看到个人介绍中的巴贝奇的分析机&#xff0c;突然觉得头像很是眼熟。 最近刚读了《人工智能简史》&#xff0c;第4章——从汇编语言到TensorFlow&#xff0c;人工智能的…

使用layui组件库制作进度条

使用layui组件库制作进度条 html代码 <!DOCTYPE html> <html> <head><meta charset"UTF-8"><title>Example</title><!-- 引入 layui 的 CSS 文件 --><link rel"stylesheet" href"https://cdn.staticfil…

Day948.组件化成熟度评估,你的目的地在哪里呢 -系统重构实战

组件化成熟度评估&#xff0c;你的目的地在哪里呢 Hi&#xff0c;我是阿昌&#xff0c;今天学习记录的是关于组件化成熟度评估&#xff0c;你的目的地在哪里呢的内容。 一、组件化成熟度模型 组件化成熟度模型可以帮助咱全局去思考当前的现状&#xff0c;并制定更有针对性的…