当前位置: 首页 > news >正文

OC内存管理

一、MRC  手动引用计数

  一个对象 alloc 之后其引用计数为1,需要对应一个 release 操作,此外,每有一个 retain 操作也要对应一个 release 操作。当一个对象的引用计数为0时(可以通过 retainCount 来获取,但不一定准确),就会销毁该对象,并调用该对象的 dealloc 方法。

  对于对象组合的情况,当一个对象使用另一个对象时,需要使其引用计数+1,比如set方法,但如果set前后为同一个对象,会导致引用计数变多,此时需要判断set的新对象不是原成员对象,然后对原成员对象 release ,而对新对象进行 retain,该操作可以通过 @property (retain) 来智能完成。

  当两个对象互相引用时,向上面的操作也会使引用计数错误(多1),此时可以将其中一个对象的引用设置成 assign ,并在其 dealloc 函数中取消该成员的 release 操作。

  整体代码如下:

 1 #import <Foundation/Foundation.h>
 2 
 3 @class Room;
 4 @class User;
 5 
 6 /******************************/
 7 @interface User : NSObject
 8 
 9 //@property(nonatomic,retain) Room *room;
10 @property(nonatomic,assign) Room *room;
11 
12 @end
13 
14 @implementation User
15 
16 - (void)dealloc
17 {
18     NSLog(@"%s",__func__);
19     //[_room release];
20     [super dealloc];
21 }
22 
23 @end
24 
25 /******************************/
26 @interface Room : NSObject
27 
28 @property(nonatomic,retain)User *user;
29 
30 @end
31 
32 @implementation Room
33 
34 - (void)dealloc
35 {
36     NSLog(@"%s",__func__);
37     
38     [_user release];
39     [super dealloc];
40 }
41 @end
42 
43 /******************************/
44 int main(int argc, const char * argv[]) {
45     User *user = [[User alloc] init];
46     Room *room = [[Room alloc] init];
47     user.room = room;
48     room.user = user;
49     
50     [user release];
51     [room release];
52 }

   自动释放池是以栈的结构存在的,先进后出。通过 @autoreleasepool 代码段创建自动释放池,在代码段内调用对象的 autorelease 方法就可以将对象放入自动释放池,在自动释放池生命周期结束时,会将该对象的引用计数-1。改写 main 函数如下:

 1 int main(int argc, const char * argv[]) {
 2     @autoreleasepool {
 3         User *user = [[[User alloc] init] autorelease];
 4         Room *room = [[[Room alloc] init] autorelease];
 5         
 6         user.room = room;
 7         room.user = user;
 8         
 9         //[user release];
10         //[room release];
11     }
12     
13     //IOS5之前的老代码还可以这样创建自动释放池,现在不推荐,能看懂即可。
14     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
15     //coding
16     [pool release];
17     
18     return 0;
19 }

 

  因为自动释放池使用的是延迟释放机制,所以不推荐将非常占内存的对象交给自动释放池管理,此外还有一些细节,比如不适宜在循环体内创建的对象交给同一个自动释放池管理。 自动释放池可以嵌套,而自动释放池也是栈结构,将一个对象进行 autorelease 操作,会自动将该对象放于栈顶的释放池进行管理。

  Foundation 库中几乎所有的类工厂方法,都是内部使用了 autorelease 方法。  

 

二、ARC  自动引用计数

  是编译器特性而不是运行时特性,不同于其它语言中的垃圾回收。它不允许程序员在程序手动调用 retain/release/autorelease 方法。

  ARC的判断原则:只要还有一个强指针(__strong,对应的弱指针为 __weak)变量指向对象,对象就会保持在内存中。比如唯一的强指针变量超出生命周期,或者手动设置该强指针变量为 nil,都会触发 ARC 销毁指向的对象。所以开发中,不要使用一个弱指针保存一个刚刚创建的对象,因为一创建就被销毁了。

  ARC中,如果一个对象想拥有另一个对象,只需要用一个强指针指向该对象,@property 中不使用 retain,而是使用 strong/weak/assign。

  与 MRC 类似,当两个对象互相引用时,则一边使用 strong ,一边使用 weak。

  Xcode 支持将 MRC 项目转化成 ARC 项目,也可以自己转换,上面的例子转成 ARC 项目如下:

 1 #import <Foundation/Foundation.h>
 2 
 3 @class Room;
 4 @class User;
 5 
 6 /******************************/
 7 @interface User : NSObject
 8 
 9 @property(nonatomic,weak) Room *room;
10 
11 @end
12 
13 @implementation User
14 
15 - (void)dealloc
16 {
17     NSLog(@"%s",__func__);
18 }
19 
20 @end
21 
22 /******************************/
23 @interface Room : NSObject
24 
25 @property(nonatomic,strong)User *user;
26 
27 @end
28 
29 @implementation Room
30 
31 - (void)dealloc
32 {
33     NSLog(@"%s",__func__);
34     
35 }
36 @end
37 
38 /******************************/
39 int main(int argc, const char * argv[]) {
40     User *user = [[User alloc] init];
41     Room *room = [[Room alloc] init];
42     
43     user.room = room;
44     room.user = user;
45     return 0;
46 }

 

转载于:https://www.cnblogs.com/tianyajuanke/p/7324665.html

相关文章:

  • MySQL入门(二)
  • 助力合作伙伴引领“互联网+”变革 浪潮预发布高端存储
  • 七:zooKeeper开源客户端ZkClient的api测试
  • 定时任务crontab在书写时的四大坑
  • YUM仓库的部署
  • Laravel 中的一个后期静态绑定
  • 简单使用JSTL攻略
  • Powershell 编写和运行脚本
  • windos 下端口被占用
  • git与eclipse相关
  • 一个在ActionBar上显示图标和菜单PopupMenu的小示例(19)
  • 管理大数据:监测系统创造新的收益
  • 使用Jmeter创建ActiveMQ JMS POINT TO POINT请求
  • select 遇到的坑
  • iOS开发文件夹--Copy items if needed
  • bearychat的java client
  • Elasticsearch 参考指南(升级前重新索引)
  • Git 使用集
  • Java Agent 学习笔记
  • JAVA 学习IO流
  • JavaScript设计模式系列一:工厂模式
  • linux学习笔记
  • Vue 2.3、2.4 知识点小结
  • 新手搭建网站的主要流程
  • 一道闭包题引发的思考
  • 一起来学SpringBoot | 第十篇:使用Spring Cache集成Redis
  • ​LeetCode解法汇总2670. 找出不同元素数目差数组
  • # 再次尝试 连接失败_无线WiFi无法连接到网络怎么办【解决方法】
  • #git 撤消对文件的更改
  • #Linux(帮助手册)
  • (done) NLP “bag-of-words“ 方法 (带有二元分类和多元分类两个例子)词袋模型、BoW
  • (每日持续更新)信息系统项目管理(第四版)(高级项目管理)考试重点整理第3章 信息系统治理(一)
  • .NET Reactor简单使用教程
  • .Net Web项目创建比较不错的参考文章
  • .net 获取url的方法
  • .net 简单实现MD5
  • .NET 中创建支持集合初始化器的类型
  • .NET6 开发一个检查某些状态持续多长时间的类
  • .NET开发不可不知、不可不用的辅助类(三)(报表导出---终结版)
  • .NET下ASPX编程的几个小问题
  • .skip() 和 .only() 的使用
  • [AHOI2009]中国象棋 DP,递推,组合数
  • [AI]ChatGPT4 与 ChatGPT3.5 区别有多大
  • [ai笔记4] 将AI工具场景化,应用于生活和工作
  • [AX]AX2012 AIF(四):文档服务应用实例
  • [bug总结]: Feign调用GET请求找不到请求体实体类
  • [BUUCTF 2018]Online Tool
  • [BUUCTF]-Reverse:reverse3解析
  • [BZOJ2208][Jsoi2010]连通数
  • [codeforces]Levko and Permutation
  • [codevs 1288] 埃及分数 [IDdfs 迭代加深搜索 ]
  • [codevs 1296] 营业额统计
  • [COI2007] Sabor
  • [DAU-FI Net开源 | Dual Attention UNet+特征融合+Sobel和Canny等算子解决语义分割痛点]
  • [Excel] vlookup函数