IOS 学习笔记14 内存管理(2)内存管理策略
来源:互联网 发布:炭知天下电话 编辑:程序博客网 时间:2024/05/29 15:31
现在搞iphone开发,一直不是很懂object-c的内存管理机制,看到apple的官方文档写的不错而又没有找到翻译的文章。于是自己在学习它的过程中就顺便把它翻译了,自己的英语不是太好,文字组织能力那就更菜了,读的蹩脚之处还望大家指出,我好在以后的翻译过程中好好改正。第一次翻译,欢迎拍砖,可不要把我拍死了呀!!!
文章中带有LPSTUDY的字样表明是我个人的理解,可能会有不对的地方,敬请指教。
文章原文链接地址:
- http://developer.apple.com/library/mac/#documentation/cocoa/conceptual/MemoryMgmt/Articles/mmRules.html#//apple_ref/doc/uid/20000994-BAJHFBGH
本文博客地址:
http://blog.csdn.net/lipeng08/article/details/7702707
内存管理策略
在引用计数机制下,你可以采用NSObject protocol的方法和和标准的方法命名约定进行内存管理。NSObject也定义了一个dealloc方法,它在对象被释放的时候自动触发。本篇文章描述了在Cocoa中你需要了解的所有内存管理的基本规则,也提供了一些实例来让你正确的使用它。
基本内存管理规则
内存管理模型是建立在对象所有者基础上的,任何一个对象都可能有一个或者多个拥有着。只要一个对象至少有一个所有者,那么它就继续存在,如果没有拥有者,它就被自动释放。因此,你需要确定何时你拥有一个对象,何时你不再拥有它。Cocoa遵循以下的约定:
· 你拥有你自己创建的对象
你可以通过使用“alloc”,“new”,“copy”或者“mutableCopy”这样的方法来创建对象。
· 你可以使用retain来获取对象的所有权
不会翻译:Areceived object is normally guaranteed to remain valid within the method it wasreceived in, and that method may also safely return the object to its invoker.你在两种情况下使用retain,(1)在存取方法或者init方法中,为了给自己的数据赋值。(2)由于一些其他的操作的副作用可能导致你的对象失效,此时你需要调用retain操作 (as explained in “AvoidCausing Deallocation of Objects You’re Using”)
· 当你不再使用某一个对象,放弃它的所有权
你可以通过发送release或者autorelease消息来释放对象的所有权。在cocoa术语中,放弃对象的所有权意味着“释放”一个对象
· 当你不再拥有一个对象时,你不能释放它
这个与前面陈述的规定相一致
简单的例子
为了展示那些规定,看看下面的代码片段
{
Person *aPerson = [[Person alloc] init];
// ...
NSString *name = aPerson.fullName;
// ...
[aPerson release];
}
通过使用alloc方法,Person对象被创建,因此当它不再被使用时,它随后调用release方法。Person的姓名没有使用任何的获取拥有权的方法,因此它也没有调用release方法。注意:本例子使用了release而不是autorelease
使用autorelease发送延迟释放消息
当你需要发送延迟释放消息的时候,你可以使用autorelease,典型的使用时候是当你需要从一个方法中返回一个对象。例如,你可以像这样实现fullName方法:
- (NSString *)fullName {
NSString *string = [[[NSString alloc] initWithFormat:@"%@ %@",
self.firstName, self.lastName] autorelease];
return string;
}
你通过带调用alloc方法拥有了这个字符串。为了遵循内存管理规则,在你失去对string的访问权限之前,你必须释放string的所有权。如果你采用了release方法,那么string就会在它被返回之前被释放.通过使用autorelease,你表明你想去释放拥有权,但是你又允许方法的调用者在它释放之前去使用返回的字符串。
你也可以像下面这样实现fullName方法:
- (NSString *)fullName {
NSString *string = [NSString stringWithFormat:@"%@ %@",
self.firstName, self.lastName];
return string;
}
遵循基本的规则,你通过调用stringWithFormat,你并没有拥有string。因此,你可以安全的从方法中返回string。
作为对照,下面的实现是错误的
- (NSString *)fullName {
NSString *string = [[NSString alloc] initWithFormat:@"%@ %@",
self.firstName, self.lastName];
return string;
}
通过命名的约定,毫无疑问fullName的调用者拥有了返回的string,但是调用者没有任何理由去释放返回的string,于是string所占用的内存泄露了。
你并不拥有返回引用的对象的所有权
在cocoa中有一些方法是通过引用返回的(也就是说,它们传递了一个这样的参数ClassName ** or id *).一个通常的模式是使用NSError对象来返回错误的详细信息,如 initWithContentsOfURL:options:error: (NSData)andinitWithContentsOfFile:encoding:error: (NSString).
在这些情况下,上述描述的规则依然适用。当你触发它们的任何一个方法的时候,你并没有创建NSError对象,因此你并没有拥有它,你也就没有必要去释放它。例子如下:
NSString *fileName = <#Get a file name#>;
NSError *error = nil;
NSString *string = [[NSString alloc] initWithContentsOfFile:fileName
encoding:NSUTF8StringEncoding error:&error];
if (string == nil) {
// Deal with error...
}
// ...
[string release];
释放所有者对象的dealloc的实现
NSObject定义了一个dealloc方法,当一个对象没有拥有者而且它的内存被回收的时候,dealloc方法会被自动触发。Dealloc方法是为了释放对象的内存,安排它所拥有的资源,当然这也包含它拥有的实例变量。
下面的例子展示了在Person 类中怎么使用dealloc方法
@interface Person : NSObject {}
@property (retain) NSString *firstName;
@property (retain) NSString *lastName;
@property (assign, readonly) NSString *fullName;
@end
@implementation Person
@synthesize firstName=_firstName, lastName=_lastName;
// ...
- (void)dealloc
[_firstName release];
[_lastName release];
[super dealloc];
}
@end
Attention:
· 你从不要去主动触发另一个对象的dealloc方法。
· 在自己的dealloc实现的末尾,你必须触发基类的dealloc方法
· 你不应该把系统资源的管理和对象的生命周期绑定到一起。see “Don’t Usedealloc to Manage Scarce Resources.
· 当程序终止时,对象可能并没有触发dealloc方法。由于在程序退出的时候,程序所占有的内存被自动清理,因此,仅仅让操作系统自己去清理资源比单纯的触发内存管理方法更有效。
Core Foundation使用相似但是不同的规则
对于Core Foundation,有相似的内存管理规则(see MemoryManagement Programming Guide for Core Foundation). 但是,Cocoa和Core Foundation的命名规范是不同的,特别的是:CoreFoundation的创建(see “The CreateRule” in MemoryManagement Programming Guide for Core Foundation)
规则并不适用于返回object-c对象的方法。例如,在下面的代码片段,你不需要释放myInstance的所有权。
MyClass *myInstance = [MyClass createInstance];
- IOS 学习笔记14 内存管理(2)内存管理策略
- iOS 内存管理策略
- IOS学习笔记:内存管理
- iOS内存管理学习笔记
- IOS 学习笔记14 内存管理(3) 有效的内存管理 前半部分
- IOS 学习笔记14 内存管理(3)有效的内存管理 后半部分
- IOS 学习笔记14 内存管理(1)
- iOS笔记:内存管理
- iOS笔记:内存管理
- iOS 内存管理笔记
- IOS内存管理笔记
- iOS学习笔记20131125-内存管理
- iOS学习笔记基础-oc06内存管理
- 【iOS学习笔记】ARC内存管理
- iOS学习笔记-----内存管理初探
- C++内存管理学习笔记(2)
- 内存管理学习笔记
- 操作系统--内存学习笔记(2)进程内存管理--虚拟内存
- 如何利用response.addHeader()方法设置cookie
- IOS沙盒机制(SandBox)
- 动态类型(isKindOfClass, isMemberOfClass,id)等
- obj-c编程10:Foundation库中类的使用(4)[文件管理,查询当前进程信息]
- 第17章 数据库和XML
- IOS 学习笔记14 内存管理(2)内存管理策略
- 全栈JavaScript之路(八)学习 CDATASection 类型 节点
- 读取httponly cookie
- 创建ORACLE实例与设置监听器过程
- Eclipse+mingw+Qt绿色配置方法(Windows下)
- 【Hadoop】Call to localhost/127.0.0.1:8020 failed on connection exception
- 绕过App Store 给iOS设备 安装应用程序
- IOS 学习笔记14 内存管理(3) 有效的内存管理 前半部分
- SNMP Linux安装