写点什么

iOS 内存管理(基本概念及引用计数)

作者:NewBoy
  • 2022 年 7 月 19 日
  • 本文字数:1648 字

    阅读完需:约 5 分钟

内存管理重要性

  • 移动设备的内存极其有限,每个 APP 所占的内存都是有限的

  • 下列行为就会增加一个 APP 的内存占用

  • 创建一个 OC 对象

  • 定义一个变量

  • 调用一个函数或者方法

  • 当 APP 所占用内存较多时,系统会发出内存警告,这时得回收一些不需要再次使用的内存空间,比如收一些不需要使用的对象、变量等

  • 若果 APP 占用内存过大,系统会强制关闭 APP,造成闪退,影响用户体验



内存管理

  • 内存管理:就是管理内存的分配和清除

  • 内存管理涉及的操作有:

  • 分配内存:比如创建一个对象,会增加内存占用

  • 清楚内存:比如销毁一个对象,能减少内存占用

  • 内存管理范围

  • 任何继承 NSObject 的对象

  • 对其他非对象类型无效(int char float double struct enum 等)


注:

为什么只有 OC 对象才需要进行内存管理的本质原因

  • OC 对象存放于堆里面(堆内存系统不会自动释放,需要手动释放)

  • 非 OC 对象一般放在栈里面(栈内存会被系统自动回收释放)



堆和栈

  • 栈(操作系统):由操作系统自动分配释放空间,存放函数的参数值,局部变量的值等,其操作方式类似于数据结构中的栈的先进后出

  • 堆(操作系统):一般由程序员分配释放空间,若程序员不释放,程序结束时可能由 OS 回收,分配方式类似于链表


//这个方法结束后,栈里的变量a、p会被回收,堆里的Person对象还会留在内存中,因为它的引用计数还是1-(void)doSomething{  //a:栈  int a = 10;  //p:栈  //Person:堆  Person *p = [[Person alloc]init];}
复制代码

引用计数器

OC 语言使用引用计数来管理内存,每一个对象都有一个可以递增递减的计数器,如果引用这个对象,那么这个对象的引用计数递增,如果不用了,那么这个对象引用计数递减,直到引用计数为 0,这个对象就可以销毁了



引用计数器的作用

  • 表示对象被引用的次数

  • 查看某对象的引用计数调用- (NSUInteger)retainCount

  • 当使用allocnewcopy创建一个对象时,对象的引用计数器默认为 1

  • 当没有任何人使用这个对象时,系统才会回收这个对象

  • 当对象的引用计数器为 0 时,对象占用的内存才会被回收

  • 如果对象的引用计数不为 0,这个对象占用的内存就不可能被回收(除非整个程序已经退出)



引用计数器的原理

  • 给对象发送一条retain消息,这个对象的引用计数值+1

  • 给对象发送一条release消息,这个对象的引用计数值-1

  • 给对象发送retainCount消息,可以获得当有对象的引用计数注:<br>release并不代表销毁或回收对象,仅仅是计数器-1



属性存取方法中的内存管理(retain、copy、assign)

  • readonly: 只会生成getter方法

  • readwrite:既会生成getter也会生成setter方法,默认什么不写就是 readwrite

  • getter:可以给生成的getter方法起一个名字

  • setter:可以给生成的setter方法起一个名字

  • retain: 会自动帮我们生成setter方法内存管理的代码

  • assign:不会帮我们生成setter方法内存管理的代码,仅仅只会生成普通的getter/setter方法,默认什么都不写就是assign

  • nonatomic:多线程中使用,性能低(默认)

  • atomic:多线程中使用,性能高


- (void)setName:(NSString *)name{    if (_name != name) {//先判断传进来的是不是新对象        [_name release];  //把_name以前的对象release        _name = [name retain]; //把name对象的地址赋给_name,这时name和_name共同指向同一个对象    }}
- (void)setName:(NSString *)name{ if (_name != name) { [_name release];//把_name以前的对象release _name = [name copy];//把name对象的地址拷贝一份给_name }}-(void)setName:(NSString *)name{ _name = name; //直接赋值}
复制代码



dealloc 方法

  • 当一个对象的引用计数器值为 0 的时候,这个对象即将被释放,其占用的内存被系统收回

  • 对象即将被销毁时系统会自动给对象发送一条dealloc的消息(因此,从dealloc方法有没有被调用就可以判断出对象是否被销毁)

  • dealloc方法重写

  • 一般重写dealloc方法,在这里释放相关资源(移除监听者、移除 coreFoundation 对象等等)

  • 在 MRC 下,一旦重写dealloc方法,就必须调用[super dealloc],并且放在最后调用

  • 使用注意

  • 不直接调用dealloc

  • 不要在dealloc方法中调用其他方法

  • 一旦对象被回收了,它占的内存就不再可用

发布于: 刚刚阅读数: 4
用户头像

NewBoy

关注

虽不年少,艳阳高照 2019.04.10 加入

还未添加个人简介

评论

发布
暂无评论
iOS 内存管理(基本概念及引用计数)_ios_NewBoy_InfoQ写作社区