继上一篇之后,再来讲述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内存管理详细解说(二)相关推荐

  1. iPhone内存管理详细解说(一)

    iPhone内存管理详细解说系列转载来源:http://keywind.me/blog/2011/05/07/iphonenei-cun-guan-li-xiang-xi-jie-shuo-yi/ 感 ...

  2. C语言内存管理内幕(二)----半自动内存管理策略

    2019独角兽企业重金招聘Python工程师标准>>> C语言内存管理内幕(二)----半自动内存管理策略 转载于:https://my.oschina.net/hengcai001 ...

  3. 内存管理(二) ARC

    内存管理(二) ARC 上篇我们介绍了MRC,本篇我们介绍下ARC ARC概述 ARC是一种编译器功能,它通过LLVM编译器和Runtime协作来进行自动管理内存.LLVM编译器会在编译时在合适的地方 ...

  4. Linux内存管理(二)

    Linux内存管理之二:Linux在X86上的虚拟内存管理 本文档来自网络,并稍有改动. 前言 Linux支持很多硬件运行平台,常用的有:Intel X86,Alpha,Sparc等.对于不能够通用的 ...

  5. 同样学习Linux, 为何差别这么大? - 论打通Linux进程和内存管理任督二脉

    穆赫兰道和内陆帝国 我在多年的工程生涯中发现很多工程师碰到一个共性的问题:Linux工程师很多,甚至有很多有多年工作经验,但是对一些关键概念的理解非常模糊,比如不理解CPU.内存资源等的真正分布,具体 ...

  6. iphone内存管理

    http://hi.baidu.com/spopavenvldiqyr/item/c8d620b6282c4d4abb0e122a iphone内存管理(一) BY 洋葱头 http://hi.bai ...

  7. iphone内存管理(二)

    (2)尽量避免使用autorelease 虽然autorelease非常简单有用,但是在iphone上一定要谨慎使用,毕竟iphone内存相当有限.autorelease可能会导致直接的隐型内存泄露. ...

  8. iPad/iPhone内存管理四之viewDidUnload/dealloc详细解说

    在进行内存管理时,我们必须要知道这两者的区别时什么. viewDidUnload是在程序接到内存警告的时候调用的,在这时候,我们可以把我们不需要的东西去掉或者让他等于nil. dealloc是在计数等 ...

  9. FreeRTOS--堆内存管理(二)

    堆内存管理代码具体实现 heap_1 内存申请函数 内存释放函数 heap_2 内存块 内存堆初始化函数 内存块插入函数 内存申请函数 判断是不是第一次申请内存 开始分配内存 内存释放函数 heap_ ...

最新文章

  1. C++学习网站。两个 CodeProject,Codeguru
  2. C++ Primer 5th笔记(chap 18 大型程序工具)未命名的命名空间unnamed namespace
  3. Administrator用户被禁用
  4. Hibernate脏检查的剖析
  5. 【机器学习-数据科学】第二节:ipython开发环境搭建以及pandas快速入门
  6. SQL开头quoted和ansiNULL
  7. nginx 小简单指令
  8. jmeter 能调用python吗_jmeter 执行python脚本的方法 。(亲测ok)
  9. splay区间翻转(bzoj 3223: Tyvj 1729 文艺平衡树)
  10. 两个小的java程序,用于练习java基本语法
  11. U盘因为有写保护,不能格式化,该怎么办
  12. PR 2019 快速入门(8)
  13. 【转载】java版打字练习软件
  14. 打开共享文件提示服务器空间不足,访问网络共享报告“服务器存储空间不足,无法处理此命令”...
  15. 如何将纯色背景的图片转换为背景透明的图片
  16. 超声波的四个特性_超声波的几个特性
  17. 这些前端资源,你值得拥有
  18. 用TMS320c54x汇编语言求方差,TMS320C54x的指令.pdf
  19. 进入U盘PE系统无法识别硬盘分区的原因分析和解决方法
  20. Arduino 光敏电阻

热门文章

  1. Word2007从指定页插入页码,不包括封面和目录,指定页为首页第1页
  2. can协议crc计算_CAN总线通信的CRC校验方法
  3. 砥砺奋进!GitChat 发布 1.9 版本更新公告
  4. 看到的有意思的文章(一)
  5. 小白一键重装有linux,linux小白说说用linux的感受
  6. Java学习从这里开始
  7. 百度apollo自动驾驶planning代码学习-Apollo/modules/planning/common/Smoother类代码详解
  8. 乡愁 - 怀念老者余光中
  9. windows软件窗口或者对话框太大超出屏幕解决办法
  10. apk私钥_Android应用apk的程序签名详解