[iOS] OC高级编程 - 引用计数 (1)

[iOS] OC高级编程 - 引用计数 (1)

文章目录

前言

引用计数是 iOS 开发中非常重要的一部分内容,仅以本篇博客做此记录,以及介绍引用计数。

ARC 与 MRC

iOS下内存管理的基本思想就是引用计数,通过对象的引用计数来对内存对象的生命周期进行控制。具体到编程时间方面,主要有两种方式:

1:MRC(manual retain-release),人工引用计数,对象的生成、销毁、引用计数的变化都是由开发人员来完成。

2:ARC(Automatic Reference Counting),自动引用计数,只负责对象的生成,其他过程开发人员不再需要关心其销毁,使用方式类似于垃圾回收,但其实质还是引用计数。

引用计数机制

书里有这么一个思路我们可以去理解这部分内容

就是通过照明设备来比喻,如果把对象比作照明设备,对象的使用环境就相当于上班进入办公室的人,如上图所演示的来的第一个人就要开灯,走的最后一个人就要关灯,只要有一个人工作,照明设备就不可以被关闭。

这个比喻也是非常形象的,它同时还可以表示那一个被计数的过程,首先开始在没有人的状态下时引用计数为 0,后面有第一个人后,引用计数为 1,然后再来一个人引用计数为 2,在有人离开时引用计数减一,最后一个人离开时再减一,这时灯就被关掉了。类比到对象就是对象被废弃掉了。

上面这张图就详细展示了这个引用计数的几个步骤。

内存管理的思考方式

有关于引用计数,正确的思考方式有四条准则:

  • 自己生成的对象,自己所持有
  • 非自己生成的对象,自己也能持有
  • 不再需要自己持有的对象时释放
  • 非自己持有的对象无法释放

自己生成的对象自己持有

使用 alloc,new,copy,mutablecopy 这几个开头的方法名意味着自己生成的对象自己持有。

就比如这段代码

objc 复制代码
// 自己生成并持有对象
id obj = [[NSobject alloc] init];

使用 NSObject 的类方法就能自己生成并持有对象,指向生成并持有对象的指针被赋给变量 obj。同时 new 类方法也能生成并持有对象。

copy方法基于NSCopying方法约定,由各类实现的copyWithZone:方法生成并持有对象的副本,mutableCopy也一样,二者区别只在于生成的对象是否可变。这些方法生成的对象,虽然是对象的副本,但也属于"自己生成并持有对象"。

非自己生成的对象,自己也能持有

用除了上面介绍的(alloc/new/copy/mutablecopy 以外的方法)获得的对象,因为并非自己生成,所以自己并不是该对象的持有者。

objc 复制代码
id obj = [NSMutableArray array];

在下面这段代码中,NSMutableArray 类对象被赋给变量 obj,但是变量 obj 自己并不持有该对象,使用 retain 方法可以持有该对象。

objc 复制代码
//取得非自己生成并持有的对象
id obj = [NSMutableArray array];
//取得的对象存在,但自己不持有对象
[obj retain];
//自己持有对象

不需要自己持有的对象时释放

自己一旦不再需要自己持有的对象,那么持有者就有义务去释放该对象,使用 release 方法。

objc 复制代码
id obj = [[NSObject alloc] init];
[obj release];
//对象一经释放绝对不可访问

这样对象就被 release 方法释放掉了,自己生成而非自己持有的对象,如果使用 retain 变成自己持有的,同样可以 release 释放。

objc 复制代码
id obj = [NSMutableArray array];
[obj retain];
[obj release];

如果要使用某个方法生成对象,并将其返还给该方法调用方

objc 复制代码
- (id)allocObject {
  id obj = [[NSObject alloc] init];
  return obj;
}

如上例,将用alloc方法生成的对象直接返回。就能让调用方也持有该对象。注意,这里与上文命名规则相符合,使用allocObject也就意味着"自己生成并持有对象"那像[NSMutableArray array]这种方法使取得的对象存在,但自己不持有对象,又是如何实现的呢?根据上文规则,不能使用alloc/new/copy/mutableCopy开头的方法名,因此我们使用object这个方法名

objc 复制代码
- (id)object {
id obj = [[NSObject alloc] init];
[obj autorelease];
//取得对象存在,但自己不持有对象
return obj;
}

在这里我们用到了 autorelease 方法,用这个方法可以使对象存在,但自己不持有对象。

无法释放非自己持有的对象

自己持有的对象释放完以后不需要再次释放。

objc 复制代码
id obj = [[NSObject alloc] init];
[obj release];
[obj release];
//应用程序崩溃!
//访问已经废弃的对象时崩溃

或者取得的对象存在,但自己不持有对象时释放

objc 复制代码
id obj1 = [obj0 object];
//取得对象存在,但自己不持有
[obj1 release];
//程序崩溃
相关推荐
T1an-12 小时前
最右IOS岗一面
ios
踏着七彩祥云的小丑2 小时前
Mac——已安装工具查找
macos
小红的布丁2 小时前
公网 IP、私网 IP、路由表、转发表与 MAC 地址的关系
tcp/ip·macos·智能路由器
Lecxcy_Kastreain3 小时前
如何自适应 MacOS
macos
坏小虎4 小时前
Expo 快速创建 Android/iOS 应用开发指南
android·ios·rn·expo
光影少年5 小时前
Android和iOS原生开发的基础知识对RN开发的重要性,RN打包发布时原生端需要做哪些配置?
android·前端·react native·react.js·ios
北京自在科技5 小时前
Find My 修复定位 BUG,AirTag 安全再升级
ios·findmy·airtag
简单点了5 小时前
mac安装node环境
macos
简单点了6 小时前
mac安装vm装win11虚拟机
macos
Digitally6 小时前
如何不用 USB 线将 iPhone 照片传到电脑?
ios·电脑·iphone