iPhone内存管理详细解说(二)
继上一篇之后,再来讲述iPhone内存管理的细节.
四:动态内存管理
第四节就内容实质来说跟第三节的object的拥有和丢弃政策是一样的,不过是从以代码为引导的动态形式讲述.所以你会在这一节看到许多代码例子帮助你理解.核心还是那些基本的规则.
1.基本知识
主要规则还是object所有权,文档在这里重复性太大,我就只写一些值得注意的地方. 我们会看到很多类提供以”+className…”这种形式的代码(下面有例子),这在文档中叫做”convenience constructors”,记住你用这种方法返回而来的object你是没有所有权的,所以没有责任去释放.
2.一些简单的例子
以下三个例子较为简单地介绍用alloc或convenience constructor或accessor method得到object的区别,看代码:
- (void)printHello {NSString *string;string = [[NSString alloc] initWithString:@"Hello"];NSLog(string);[string release];
}
你用alloc得到的string,有义务用release释放.
- (void)printHello {NSString *string;string = [NSString stringWithFormat:@"Hello"];NSLog(string);
}
你用convenience constructor得到的string,放心地不用再管它了.
- (void)printWindowTitle {NSString *string;string = [myWindow title];NSLog(string);
}
你用accessor method得到的string,跟convenience constructor一样,放心地不用再管它了.
3.使用Accessor Methods
官方文档的建议是:相对于频繁的使用retain和release,更好的做法是使用accessor methods.比如我有这么一个object,它的类声明是:
@interface Counter : NSObject {NSNumber *count;
}
为了get和set这个count,你要定义两个accessor methods(下面的例子较为简单,详细的accessor methods在后面几节会讲述).get是:
- (NSNumber *)count {return count;
}
set稍微复杂点:
- (void)setCount:(NSNumber *)newCount {[newCount retain];[count release];// make the new assignmentcount = newCount;
}
因为你要防止newCount被别人释放了,所以你需要有拥有权,同时把之前你占有所有权的那个count释放掉.
上面提到推荐使用accessor methods,不过在init方法和dealloc里则例外,比如在init里你需要这么写:
- init {self = [super init];if (self) {count = [[NSNumber alloc] initWithInteger:0];}return self;
}
如果想灵活一点使其可以自己设定值,可以:
- initWithCount:(NSNumber *)startingCount {self = [super init];if (self) {count = [startingCount copy];}return self;
}
而在dealloc里,则需要释放count:
- (void)dealloc {[count release];[super dealloc];
}
实现一个reset重置方法: 你可以有两种方法:
(1)使用convenience constructor,很省心地不用再考虑何时释放:
- (void)reset {NSNumber *zero = [NSNumber numberWithInteger:0];[self setCount:zero];
}
(2)使用传统的alloc,需要释放:
- (void)reset {NSNumber *zero = [[NSNumber alloc] initWithInteger:0];[self setCount:zero];[zero release];
}
常见错误 (1)不使用accessor methods,那么你经常会忘记retain或release而犯错,如:
- (void)reset {NSNumber *zero = [[NSNumber alloc] initWithInteger:0];[count release];count = zero;
}
(2)实例内存泄漏,如:
- (void)reset {NSNumber *zero = [[NSNumber alloc] initWithInteger:0];[self setCount:zero];
}
忘记release后,这个zero你再也release不掉了.
(3)release没有所有权的实例,如:
- (void)reset {NSNumber *zero = [NSNumber numberWithInteger:0];[self setCount:zero];[zero release];
}
4.经常引起困惑的情形
(1)使用集合类(如array, dictionary, 或 set)
当添加一个object给集合类的实例时,这个集合类的实例拥有所有权,当这个object从集合类的实例中移除时,或集合类的实例自身被release了,就会释放这个object的所有权.例如创建一个数的array,你可以:
NSMutableArray *array;
NSUInteger i;
// ...
for (i = 0; i < 10; i++) {NSNumber *convenienceNumber = [NSNumber numberWithInteger:i];[array addObject:convenienceNumber];
}
没必要retain,array就有所有权.当然你也可以:
NSMutableArray *array;
NSUInteger i;
// ...
for (i = 0; i < 10; i++) {NSNumber *allocedNumber = [[NSNumber alloc] initWithInteger: i];[array addObject:allocedNumber];[allocedNumber release];
}
(2)从方法中返回objects
这个很简单了,跟第三节也有重复,直接给出四个情形,你先自己判断一下吧:
- (NSString *)fullName {NSString *string = [NSString stringWithFormat:@"%@ %@", firstName, lastName];return string;
}- (NSString *)fullName {NSString *string = [[[NSString alloc] initWithFormat:@"%@ %@", firstName, lastName] autorelease];return string;
}- (NSString *)fullName {NSString *string = [[[NSString alloc] initWithFormat:@"%@ %@", firstName, lastName] release];return string;
}- (NSString *)fullName {NSString *string = [[NSString alloc] initWithFormat:@"%@ %@", firstName, lastName];return string;
}
很明显吧,前两个是对的,后两个是扯淡的.若对这个还有疑问,直接回复提问吧.
iPhone内存管理详细解说(二)相关推荐
- iPhone内存管理详细解说(一)
iPhone内存管理详细解说系列转载来源:http://keywind.me/blog/2011/05/07/iphonenei-cun-guan-li-xiang-xi-jie-shuo-yi/ 感 ...
- C语言内存管理内幕(二)----半自动内存管理策略
2019独角兽企业重金招聘Python工程师标准>>> C语言内存管理内幕(二)----半自动内存管理策略 转载于:https://my.oschina.net/hengcai001 ...
- 内存管理(二) ARC
内存管理(二) ARC 上篇我们介绍了MRC,本篇我们介绍下ARC ARC概述 ARC是一种编译器功能,它通过LLVM编译器和Runtime协作来进行自动管理内存.LLVM编译器会在编译时在合适的地方 ...
- Linux内存管理(二)
Linux内存管理之二:Linux在X86上的虚拟内存管理 本文档来自网络,并稍有改动. 前言 Linux支持很多硬件运行平台,常用的有:Intel X86,Alpha,Sparc等.对于不能够通用的 ...
- 同样学习Linux, 为何差别这么大? - 论打通Linux进程和内存管理任督二脉
穆赫兰道和内陆帝国 我在多年的工程生涯中发现很多工程师碰到一个共性的问题:Linux工程师很多,甚至有很多有多年工作经验,但是对一些关键概念的理解非常模糊,比如不理解CPU.内存资源等的真正分布,具体 ...
- iphone内存管理
http://hi.baidu.com/spopavenvldiqyr/item/c8d620b6282c4d4abb0e122a iphone内存管理(一) BY 洋葱头 http://hi.bai ...
- iphone内存管理(二)
(2)尽量避免使用autorelease 虽然autorelease非常简单有用,但是在iphone上一定要谨慎使用,毕竟iphone内存相当有限.autorelease可能会导致直接的隐型内存泄露. ...
- iPad/iPhone内存管理四之viewDidUnload/dealloc详细解说
在进行内存管理时,我们必须要知道这两者的区别时什么. viewDidUnload是在程序接到内存警告的时候调用的,在这时候,我们可以把我们不需要的东西去掉或者让他等于nil. dealloc是在计数等 ...
- FreeRTOS--堆内存管理(二)
堆内存管理代码具体实现 heap_1 内存申请函数 内存释放函数 heap_2 内存块 内存堆初始化函数 内存块插入函数 内存申请函数 判断是不是第一次申请内存 开始分配内存 内存释放函数 heap_ ...
最新文章
- C++学习网站。两个 CodeProject,Codeguru
- C++ Primer 5th笔记(chap 18 大型程序工具)未命名的命名空间unnamed namespace
- Administrator用户被禁用
- Hibernate脏检查的剖析
- 【机器学习-数据科学】第二节:ipython开发环境搭建以及pandas快速入门
- SQL开头quoted和ansiNULL
- nginx 小简单指令
- jmeter 能调用python吗_jmeter 执行python脚本的方法 。(亲测ok)
- splay区间翻转(bzoj 3223: Tyvj 1729 文艺平衡树)
- 两个小的java程序,用于练习java基本语法
- U盘因为有写保护,不能格式化,该怎么办
- PR 2019 快速入门(8)
- 【转载】java版打字练习软件
- 打开共享文件提示服务器空间不足,访问网络共享报告“服务器存储空间不足,无法处理此命令”...
- 如何将纯色背景的图片转换为背景透明的图片
- 超声波的四个特性_超声波的几个特性
- 这些前端资源,你值得拥有
- 用TMS320c54x汇编语言求方差,TMS320C54x的指令.pdf
- 进入U盘PE系统无法识别硬盘分区的原因分析和解决方法
- Arduino 光敏电阻
热门文章
- Word2007从指定页插入页码,不包括封面和目录,指定页为首页第1页
- can协议crc计算_CAN总线通信的CRC校验方法
- 砥砺奋进!GitChat 发布 1.9 版本更新公告
- 看到的有意思的文章(一)
- 小白一键重装有linux,linux小白说说用linux的感受
- Java学习从这里开始
- 百度apollo自动驾驶planning代码学习-Apollo/modules/planning/common/Smoother类代码详解
- 乡愁 - 怀念老者余光中
- windows软件窗口或者对话框太大超出屏幕解决办法
- apk私钥_Android应用apk的程序签名详解