设为首页 加入收藏

TOP

iOS内存管理之MRC(一)
2023-07-23 13:26:37 】 浏览:79
Tags:iOS 管理之 MRC

前言:

在iOS中,使用引用计数来管理OC对象内存
一个新创建的OC对象引用计数默认是1,当引用计数减为0,OC对象就会销毁,释放其占用的内存空间。
调用retain会让OC对象的引用计数+1,调用release会让OC对象的引用计数-1。

内存管理的经验总结

当调用alloc、new、copy、mutableCopy方法返回了一个对象,在不需要这个对象时,要调用release或者autorelease释放它。
想拥有某个对象,就让他的引用计数+1;不想再拥有某个对象,就让他的引用计数-1。

一、 MRC 手动管理内存(Manual Reference Counting)

1、引用计数器

引用计数器:
一个整数,表示为「对象被引用的次数」。系统需要根据对象的引用计数器来判断对象是否需要被回收。

关于「引用计数器」,有以下几个特点:

  • 每个 OC 对象都有自己的引用计数器。

  • 任何一个对象,刚创建的时候,初始的引用计数为 1。

    即使用 alloc、new 或者 copy 创建一个对象时,对象的引用计数器默认就是 1。

  • 当没有任何人使用这个对象时,系统才会回收这个对象。也就是说:

    当对象的引用计数器为 0 时,对象占用的内存就会被系统回收。

    如果对象的引用计数器不为 0 时,那么在整个程序运行过程,它占用的内存就不可能被回收(除非整个程序已经退出)。

2、引用计数器操作

  • 为保证对象的存在,每当创建引用到对象需要给对象发送一条 retain 消息,可以使引用计数器值 +1 ( retain 方法返回对象本身)。
  • 当不再需要对象时,通过给对象发送一条 release 消息,可以使引用计数器值 -1。
  • 给对象发送 retainCount 消息,可以获得当前的引用计数器值。
  • 当对象的引用计数为 0 时,系统就知道这个对象不再需要使用了,所以可以释放它的内存,通过给对象发送 dealloc 消息发起这个过程。
  • 需要注意的是:release 并不代表销毁 / 回收对象,仅仅是将计数器 -1。
// 创建一个对象,默认引用计数器是 1
RHPerson *person1 = [[RHPerson alloc] init];
NSLog(@"retainCount = %zd", [person1 retainCount]);

// 只要给对象发送一条 retain 消息,引用计数器加1
[person1 retain];
NSLog(@"retainCount = %zd", [person1 retainCount]);

// 只要给对象发送一条 release 消息,引用计数器减1
[person1 release];
NSLog(@"retainCount = %zd", [person1 retainCount]);

// 当 retainCount 等于0时,对象被销毁
[person1 release];

NSLog(@"--------------");
2022-07-11 16:09:24.102850+0800 Interview01-内存管理[8035:264221] retainCount = 1
2022-07-11 16:09:24.103083+0800 Interview01-内存管理[8035:264221] retainCount = 2
2022-07-11 16:09:24.103126+0800 Interview01-内存管理[8035:264221] retainCount = 1
2022-07-11 16:09:24.103231+0800 Interview01-内存管理[8035:264221] -[RHPerson dealloc]
2022-07-11 16:09:24.103259+0800 Interview01-内存管理[8035:264221] --------------
Program ended with exit code: 0

3、dealloc 方法

  • 当一个对象的引用计数器值为 0 时,这个对象即将被销毁,其占用的内存被系统回收。
  • 对象即将被销毁时系统会自动给对象发送一条 dealloc 消息(因此,从 dealloc 方法有没有被调用,就可以判断出对象是否被销毁)
  • dealloc 方法的重写(注意是在 MRC 中)
    • 一般会重写 dealloc 方法,在这里释放相关资源,dealloc 就是对象的遗言
    • 一旦重写了 dealloc 方法,就必须调用 [super dealloc],并且放在最后面调用
- (void)dealloc {
    NSLog(@"%s", __func__);
    [super dealloc];
}

dealloc 使用注意:

  • 不能直接调用 dealloc 方法。

  • 一旦对象被回收了, 它占用的内存就不再可用,坚持使用会导致程序崩溃(野指针错误)。

    4、野指针和空指针

  • 只要一个对象被释放了,我们就称这个对象为「僵尸对象(不能再使用的对象)」。

  • 当一个指针指向一个僵尸对象(不能再使用的对象),我们就称这个指针为「野指针」。

  • 只要给一个野指针发送消息就会报错(EXC_BAD_ACCESS 错误)。

RHPerson *person1 = [[RHPerson alloc] init];
[person1 release];
[person1 release];
[person1 release];
  • 为了避免给野指针发送消息会报错,一般情况下,当一个对象被释放后我们会将这个对象的指针设置为空指针。

  • 空指针:

    • 没有指向存储空间的指针(里面存的是 nil, 也就是 0)。

    • 给空指针发消息是没有任何反应的。

      RHPerson *person1 = [[RHPerson alloc] init];
      [person1 release];
      person1 = nil;
      [person1 release];
      

二、内存管理思想

1、单个对象内存管理思想

思想一:自己创建的对象,自己持有,自己负责释放
  • 通过 allocnewcopymutableCopy 方法创建并持有对象。
  • 当自己持有的对象不再被需要时,必须调用 releaseautorelease 方法释放对象。
id obj1 = [[NSObject alloc] init];
[obj1 release];

id obj2 = [NSObject new];
[obj2 release];
思想二:非自己创建的对象,自己也能持有
  • 除了用上面方法(alloc / new / copy / mutableCopy 方法)所取得的的对象,因为非自己生成并持有,所以自己不是该对象的持有者。
  • 通过调用 retain 方法,即便是非自己创建的对象,自己也能持有对象。
  • 同样当自己持有的对象不再被需要时,必须调用 release 方法来释放对象。
id obj3 = [NSArray array];
[obj3 retain];
[obj3 release];
  • 无论是否是自己创建的对象,自己都可以持有,并负责释放。
  • 计数器有加就有减。
  • 曾经让对象的计数器 +1,就必须在最后让对象计数器 -1。

2、多个对象内存管理思想

多个对象之间往往是通过 setter 方法产生联系的,其内存管理的方法也是在 setter 方法、dealloc 方法中实现的。所以只有了解了 setter 方法是如何实现的

首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Apple Xcode 14 (14A309) 正式版.. 下一篇内存管理(二)之别小看了Tagged-..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目