10天掌握iOS开发之Day2 - 内存管理
黑马程序员:IOS面试宝典:内存管理

二. 内存管理1. 为什么要进行内存管理?因为移动设备的内存极其有限,当一个程序达到40M时, 系统会发出内存警告. 当程序达到120M时, 程序会闪退, 影响用户体验. 为了保证程序的运行流畅, 必须进行内存管理2. 内存管理的范围?管理所有继承自NSObject的对象, 对基本数据类型无效. 是因为对象和其他数据类型在系统中存储的空间不一样, 其他局部变量主要存储在栈区(因为基本数据类型占用的存储空间是固定的, 一般存放于栈区), 而对象存储于堆中, 当代码块结束时, 这个代码块所涉及到的所有局部变量会自动弹栈清空, 指向对象的指针也会被回收, 这时对象就没有指针指向, 但依然存在于堆内存中, 造成内存泄露.3.内存管理的原理是什么?1>对象的所有权及计数1) . 对象所有权的概念:任何对象都有可能拥有一个或者多个所有者, 只要对象还有至少一个所有者, 它就会继续存在2). Cocoa所有权策略:任何自己创建的对象,都归自己所有, 可以使用retain来获取一个对象的所有权, 可以使用”alloc”,”new”,”copy”的方法创建对象2>对象的引用计数器对象里面有retainCount这个实例变量: 来标识当前有多少个东西来引用这个对象注: 每个OC对象内部,都专门有一个8个字节的存储空间来存储引用计数器, 不分系统, 不管是多少位的系统, retainCount都是占8个字节1). 每个对象都有自己的引用计数器是一个整数表示对象被引用的次数, 即现在有多少东西在引用这个对象. 对象刚被创建时默认计数器值为1,因为一个对象被创建时Person * person = [[Person alloc] init] 至少有一个拥有者,就是他自己, 当计数器值变为0时, 对象被销毁2) . 引用计数器的作用:判断对象要不要回收的依据, 如果retainCount = 0 , 表示对象需要被回收(空指针nil除外)3>对象的引用计数器操作:1). 发送retain消息: 使计数器+1, 该方法返回对象本身2). 发送release消息: 使计数器-1,3). 发送retainCount消息: 获得当前对象的引用计数器值4>对象销毁1). 当引用计数器值为0, 那么该对象将会被销毁, 占据的内存空间将会被释放, 如果不为0,这不会被回收(除非整个程序退出)2). 当对象被销毁时,系统会自动发送一条dealloc 消息, 一般会重写dealloc方法, 在这里释放相关资源3). 一旦重写了dealloc方法,不能直接调用dealloc方法, 必须调用[super dealloc] , 将父类自资源也释放一次, 放在代码块最后调用4). 一旦对象被回收了,那么他所占据的存储空间就不可再用, 坚持使用程序会崩溃4. objc使用什么机制管理对象内存(或者内存管理方式有哪些)?(重点)1).MRC(manual retain-release)手动内存管理2).ARC(automatic reference counting)自动引用计数3).Garbage collection (垃圾回收)但是iOS不支持垃圾回收, ARC作为LLVM(编译器的架构系统,用c++编写而成的)3.0编译器的一项特性, 在iOS5.0 (Xcode4) 版本后推出的自动内存管理, 苹果推荐使用ARC技术来管理内存, 节约时间,提高效率,减少代码量,降低出错几率. 开发者不需要再手动写入retain,release,autorelease三个关键字,手动管理内存, 编译器将自动在代码合适的地方插入retain,release,autorelease进行内存管理.ARC的判断准则, 只要没有强指针指向对象, 对象就会被释放.5. 内存管理的原则1>原则:1). 只要还有人在使用这个对象, 那么这个对象就不会被回收2). 只有你想使用这个对象, 那么就应该让这个对象的引用计数器加13). 当你不想使用这个对象时, 应该让对象的引用计数器减12>谁创建, 就由谁来release1). 如果你通过alloc, new, copy 来创建一个对象, 当你不想用这个对象的时候就必须调用release 或者autorelease 让引用计数器减12). 不是你创建的就不用你负责release3>谁retain 谁release只要你调用了retain ,无论这个对象如何生成, 都需要调用release4>总结:有加就应该有减, 曾让某个计数器加1, 就应该让其在最后减16.内存管理研究的对象:1>野指针1). 指针变量没有进行初始化2). 指向的空间已经被释放2>内存泄露1). 如Person * person = [Person new]; 在栈区的person已经被释放, 而堆区new产生的对象还没有释放, 就会造成内存泄露2). 在MRC手动引用计数器模式下, 内存泄露分4中情况情况一: OC对象在创建完成使用之后, 没有使用release.情况二: 没有遵守内存管理的原则, 导致release的次数少于retain次数, 因为只要对象还在使用, 内存就不会被释放, 导致内存泄露情况三: 不当的使用nil, 在对象还在使用之前就将对象赋值为nil情况四: 在函数和方法中错误的使用了retain,release, 在函数中传入的对象进行了retain3>.僵尸对象: 堆中已经被释放的对象4>.空指针: 指针赋值为空,nil7. Objective-C的内存管理? 如何实现内存管理?如果您通过分配和初始化(比如[[MyClass alloc] init])的方式来创建对象,您就拥有这个对象,需要负责该对象的释放。
iOS应用开发中的性能调优与内存管理

iOS应用开发中的性能调优与内存管理在iOS应用开发中,性能调优和内存管理是至关重要的方面。
一个高性能的应用能够提供流畅的用户体验,而有效的内存管理则可以避免应用因为内存泄漏而崩溃或者占用过多的系统资源。
本文将探讨iOS应用开发中的性能调优和内存管理的一些重要技巧和策略。
一、性能调优1. 减少视图层次结构在iOS应用中,视图层次结构的深度会直接影响应用的性能。
因此,我们应该尽量减少视图的层次结构,避免过多的嵌套。
可以通过合并视图、使用Auto Layout和调整视图的层级关系来优化视图层次结构。
2. 异步加载和缓存数据在加载大量数据或者网络请求时,我们应该尽量使用异步加载的方式,并且合理地缓存数据。
异步加载可以避免阻塞主线程,提高应用的响应速度,而数据缓存则可以避免重复的网络请求,减少数据加载的时间。
3. 图像优化图像在应用中通常占据很大的资源,因此优化图像的加载和显示对于提高应用性能非常重要。
可以使用合适的图片格式(如JPEG、PNG)和压缩算法来减小图像的文件大小,使用异步加载和图片缓存来提高图像的加载速度。
4. 使用合适的数据结构和算法在应用开发中,使用合适的数据结构和算法可以大幅度提高应用的性能。
例如,使用字典(Dictionary)代替数组(Array)可以提高查找和插入的效率;使用快速排序(Quick Sort)代替冒泡排序(Bubble Sort)可以提高排序算法的效率。
二、内存管理1. 使用ARC(Automatic Reference Counting)ARC是iOS开发中的一种自动内存管理技术,可以自动地管理对象的内存生命周期。
使用ARC可以避免手动管理内存的繁琐和错误,减少内存泄漏的风险。
但是,我们仍然需要注意循环引用的问题,可以使用弱引用(weak)来解决循环引用的问题。
2. 避免循环引用循环引用是一种常见的内存泄漏问题,当两个对象相互引用时,即使没有其他对象引用它们,它们也无法被释放。
ios内存管理机制

ios内存管理机制引用计数iOS内存管理机制的核心是引用计数概念引用计数简单来说,就是管理应用程序创建的每一块内存空间的生命周期当一个对象创建时,系统就为他分配了一块内存空间,它的引用计数从0增加到1,表示有一个对象拥有这块内存的所有权;如果有另一个对象也指向这块内存空间,则它的引用计数加1变为2;之后如果一个对象不再指向这块内存空间,则它的引用计数减1,当一块内存空间的引用计数变为0,表示没有对象拥有这块内存空间,系统便会释放掉这块内存空间。
分类引用计数分为ARC(自动引用计数)和MRC(手动引用计数)ARC的本质其实也是MRC,两者的区别在于ARC是由系统来管理程序的内存空间,在系统认为合适的时间和地点释放引用计数为0的内存空间,而MRC则是由开发者自己管理内存空间的分配和释放。
ARC写代码很方便,不但减少了代码量,而且降低了内存出错的概率,但因为ARC不一定会及时释放内存空间,所以程序有时会占用比较大的内存;而MRC 通过手动管理,及时释放不需要的内存空间,就可以保证程序长时间处于良好的运行状态。
关键字引用计数的关键字有:alloc、strong、retain、copy、release、autorelease,其中strong关键字只用在ARC,作用等同于retain。
alloc创建新对象并分配内存空间,每次调用alloc都是开辟一块新的内存空间,引用计数从0增加到1;retain创建新对象指向原对象的内存空间,原对象的内存空间引用计数加1,不会开辟新内存空间;例如NSObject *obj2 =[obj1 retain];表示obj2指向并拥有obj1指向的内存空间;copy复制一个对象到一块新的内存空间上,返回一个新的对象,新对象的内存空间引用计数从0增加到1,而原对象内存空间的引用计数不会变化,虽然内容一样,但实际上是两块内存空间;copy分类:浅拷贝、普通深拷贝、真正深拷贝浅拷贝:只拷贝地址,与retain等同;普通深拷贝:拷贝内容,会开辟新的内存空间存放对象,与retain不一样;真正深拷贝:是对于容器类说的,如数组、字典、集合(包括可变和不可变类型),与普通深拷贝不同的是,真正深拷贝除了开辟新的内存空间存放容器类对象,连同容器类的元素都进行了深拷贝,为每个元素都开辟了新的内存空间。
好程序员特训营学习笔记ios内存问题

Objective-C提供了三种内存管理方式:manual retain-release(MRR,手动管理),automatic reference counting(ARC,自动引用计数),garbage collection(垃圾回收)。
iOS不支持垃圾回收;ARC作为苹果新提供的技术,苹果推荐开发者使用ARC技术来管理内存;这篇笔记主要讲的是手动管理。
内存管理的目的是:1.不要释放或者覆盖还在使用的内存,这会引起程序崩溃;2.释放不再使用的内存,防止内存泄露。
iOS程序的内存资源是宝贵的。
MRR手动管理内存也是基于引用计数的,只是需要开发者发消息给某块内存(或者说是对象)来改变这块内存的引用计数以实现内存管理(ARC技术则是编译器代替开发者完成相应的工作)。
一块内存如果计数是零,也就是没有使用者(owner),那么objective-C的运行环境会自动回收这块内存。
objective-C 的内存管理遵守下面这个简单的策略:注:文档中把引用计数加1的操作称为“拥有”(own,或者take ownership of)某块对象/内存;把引用计数减1的操作称为放弃(relinquish)这块对象/内存。
拥有对象时,你可以放心地读写或者返回对象;当对象被所有人放弃时,objective-C的运行环境会回收这个对象。
1.你拥有你创建的对象也就是说创建的对象(使用alloc,new,copy 或者mutalbeCopy等方法)的初始引用计数是1。
2.给对象发送retain消息后,你拥有了这个对象3.当你不需要使用该对象时,发送release或者autorelease消息放弃这个对象4.不要对你不拥有的对象发送“放弃”的消息注:简单的赋值不会拥有某个对象。
比如:...NSString *name = person.fullName;...上面这个赋值操作不会拥有这个对象(这仅仅是个指针赋值操作);这和C++语言里的某些基于引用计数的类的行为是有区别的。
iOS开发内存管理编程指南

内存管理编程指南介绍无论编写任何程序,您都需要确保能够有效和高效地管理资源。
程序内存就是这些资源中的一种。
在Objective-C程序中,您必须确保您所创建的对象,在不再需要它们的时候被销毁。
在一个复杂的系统中,可能很难精确地确定从何时起您不再需要某个对象。
Cocoa定义了一些有助于使这一抉择变得更加容易的规则和原则。
重要:在及更高的版本中,您可以通过采用垃圾回收机制来使用自动内存管理。
这一部分内容在垃圾回收编程指南中向您介绍。
iOS不提供垃圾回收机制。
谁应该阅读本文档如果您想要了解在引用计数环境中创建,复制,维护和销毁对象的相关技术及对象所有权的规则,您应该阅读本文档。
注意:如果您想要针对或更高的版本开发新项目,在一般情况下您应该使用垃圾回收机制,除非您有充足的理由要使用本文档描述的技术。
本文档不会向您阐述分配和初始化对象以及实现初始化方法这样的细节。
这些内容会在Objective-C编程语言的“分配和初始化对象”部分中进行讨论。
本文档的组织本文档包含以下几部分:▪“内存管理规则”总结了对象所有权和销毁的规则。
▪“对象的所有权和销毁”描述了基本的对象所有权策略。
▪“实用内存管理”以实用性的角度透视内存管理。
▪“自动释放池”描述了自动释放池—一种延迟回收的机制—在Cocoa程序中的用法。
▪“存取方法”向您介绍如何实现存取方法。
▪“实现对象复制”讨论有关对象复制的问题,比如如何决定是执行深拷贝还是浅拷贝,在您自己的子类中如何实现对象的复制。
▪“Cocoa 中Core Foundation 对象的内存管理”介绍了Cocoa代码中Core Foundation对象的内存管理技术及使用指南。
▪“Nib 对象的内存管理”讨论了与nib文件相关的内存管理的问题。
内存管理规则本文总结了Objective-C中内存管理的规则。
以下是基本规则:▪您只能释放或自动释放您所拥有的对象。
▪如果您使用名字以“alloc”或“new”开头或名字中包含“copy”的方法(例如alloc,newObject或mutableCopy)创建了一个对象,则您会获得该对象的所有权;或者如果您向一个对象发送了一条retain消息,则您也会获得该对象的所有权。
iOS内存管理就这么简单2电脑资料

iOS内存管理就这么简单2 -电脑资料文明转转和评论是对自己的尊重也是对学者的鼓励,谢谢iOS-内存管理就这么简单2今天讨论的主要内容copy,mutableCopy.一.copy,mutableCopy的使用1.NSArray *arr = [[NSArray alloc]initWithObjects:@"hello", nil]; NSArray *arr2 = [arr copy]; NSObject *obj = [[NSObjectalloc]init]; NSLog(@"arr retainCout %ld",[arr retainCount]); NSLog(@"arr2 retainCout %ld",[arr2 retainCount]); NSLog(@"arr= %ld arr2 =%ld ",arr,arr2);运行结果:2015-01-17 23:26:04.977 MemoryManager[907:40309] arr retainCout 22015-01-17 23:26:04.977 MemoryManager[907:40309] arr2 retainCout 22015-01-17 23:26:04.977 MemoryManager[907:40309] arr = 140677793151936 arr2 =140677793151936说明通过copy得到的是同一个对象,copy使堆内存对象的引用计数加一了,iOS内存管理就这么简单2。
2.NSArray *arr = [[NSArray alloc]initWithObjects:@"hello", nil]; NSArray *arr2 = [arr mutableCopy]; NSObject *obj = [[NSObjectalloc]init]; NSLog(@"arr retainCout %ld",[arr retainCount]); NSLog(@"arr2 retainCout %ld",[arr2 retainCount]); NSLog(@"arr= %ld arr2 =%ld ",arr,arr2);运行结果:2015-01-17 23:28:12.817 MemoryManager[927:41217] arr retainCout 12015-01-17 23:28:12.817 MemoryManager[927:41217] arr2 retainCout 12015-01-17 23:28:12.817 MemoryManager[927:41217] arr = 140285358613872 arr2 =140285358605248说明mutableCopy使把arr中的内容完全的赋值一份并存在新分配的堆内存对象中,所以arr和arr2指向的是不同的内存对象;NSArray *arr = [[NSArray alloc]initWithObjects:@"hello", nil]; NSArray *arr2 = [arr mutableCopy]; if([arr2respondsToSelector:@selector(addObject:)]){ NSLog(@"changed"); } NSObject *obj = [[NSObject alloc]init]; NSLog(@"arr retainCout %ld",[arr retainCount]); NSLog(@"arr2retainCout %ld",[arr2 retainCount]); NSLog(@"arr = %ld arr2 =%ld ",arr,arr2);运行结果:2015-01-17 23:32:03.639 MemoryManager[950:42492] changed2015-01-17 23:32:03.640 MemoryManager[950:42492] arr retainCout 12015-01-17 23:32:03.640 MemoryManager[950:42492] arr2 retainCout 12015-01-17 23:32:03.640 MemoryManager[950:42492] arr = 140367229411264 arr2 =140367229427648说明mutableCopy的作用相当于,NSMutableArray * arr2 =[[NSMutableArrayalloc]initWithArray:arr];3.NSMutableArray *arr = [[NSMutableArrayalloc]initWithObjects:@"hello", nil]; NSMutableArray *arr2 = [arr mutableCopy]; if([arr2respondsToSelector:@selector(addObject:)]){ NSLog(@"changed"); } NSObject *obj = [[NSObject alloc]init]; NSLog(@"arr retainCout %ld",[arr retainCount]); NSLog(@"arr2retainCout %ld",[arr2 retainCount]); NSLog(@"arr = %ld arr2 =%ld ",arr,arr2);运行结果:2015-01-17 23:38:24.378 MemoryManager[1034:44814] changed2015-01-17 23:38:24.379 MemoryManager[1034:44814] arr retainCout 12015-01-17 23:38:24.379 MemoryManager[1034:44814] arr2 retainCout 12015-01-17 23:38:24.379 MemoryManager[1034:44814] arr = 140316907672672 arr2 =140316907807120结果分析:可变数组mutableCopy还是可变数组,相当于NSMutableArray *arr2 = [[NSMutableArrayalloc]initWithArray:arr];arr和arr2还是指向不同堆中的对象,但它们的内容完全相同note:可变数组的mutableCopy之后还是可变的5.NSMutableArray *arr = [[NSMutableArrayalloc]initWithObjects:@"hello", nil]; NSMutableArray *arr2 = [arr copy]; if([arr2respondsToSelector:@selector(addObject:)]){ NSLog(@"changed"); } NSObject *obj = [[NSObject alloc]init]; NSLog(@"arr retainCout %ld",[arr retainCount]); NSLog(@"arr2retainCout %ld",[arr2 retainCount]); NSLog(@"arr = %ld arr2 =%ld ",arr,arr2);运行结果:2015-01-17 23:41:36.505 MemoryManager[1058:46071] arr retainCout 12015-01-17 23:41:36.506 MemoryManager[1058:46071] arr2retainCout 12015-01-17 23:41:36.506 MemoryManager[1058:46071] arr = 140719784280096 arr2 =140719784275712说明可变的数组通过copy函数相当于:NSArray *arr2 = [[NSArray alloc]initWithArray:arr];不同堆对象相同内容,这就是所谓的深拷贝和浅拷贝,但要注意拷贝之后的对象的属性性质的变化,其他的集合类和字符串也存在通过深拷贝和浅拷贝及对象性质的变化,所以在应用时要小心,电脑资料《iOS内存管理就这么简单2》。
代码开发中的内存管理优化技巧

代码开发中的内存管理优化技巧代码开发中的内存管理优化技巧是确保程序尽可能高效地使用内存资源的关键。
良好的内存管理优化可以提高代码的性能、减少内存泄漏和崩溃的风险,并减少内存的使用量。
以下是几个重要的内存管理优化技巧:1.使用合适的数据结构:选择合适的数据结构对于内存管理和性能是至关重要的。
例如,如果需要频繁插入和删除元素,并且不需要按顺序访问它们,那么使用链表而不是数组可以大大减少内存碎片和提高性能。
2.避免内存泄漏:内存泄漏是指动态分配的内存没有被正确释放,导致内存泄漏并最终耗尽系统资源。
使用编程语言中的自动内存管理工具(如垃圾回收器)可以减少内存泄漏的风险。
此外,确保在不再使用内存时及时释放它们也是非常重要的。
3.批量分配和释放内存:频繁地进行内存分配和释放是非常低效的。
为了减少内存分配的次数,可以使用对象池或内存池来复用已分配的内存。
这样可以避免频繁的内存分配和释放操作,提高性能。
4.合理使用缓存:内存缓存是提高性能的重要手段。
通过将经常使用的数据加载到缓存中,可以减少对慢速存储介质(如硬盘)的访问次数,提高代码的执行效率。
但是,需要注意缓存的大小和生命周期,以避免占用过多的内存资源。
5.预分配和延时分配:在代码开发中,可以使用预分配和延时分配的技术来减少内存的使用量。
预分配是在程序启动时一次性分配所需的内存,而不是在每个需要时动态分配。
延时分配是在需要时分配内存,而在不需要时将其释放。
这些技术可以减少内存碎片,提高内存使用效率。
6.内存对齐:内存对齐是指将数据存储在内存中的特定地址上,以提高数据访问的效率。
对于某些体系结构,内存对齐是必须的,否则可能会导致性能下降。
在开发代码时,确保数据结构的对齐方式与目标平台的要求一致。
7.优化内存访问模式:内存的访问模式对代码的性能有很大影响。
通过合理地组织数据的布局,可以提高内存的局部性,减少缓存未命中的次数,从而提高代码的执行效率。
例如,可以将频繁访问的数据存储在连续的内存位置上,避免跳跃式的内存访问。
iOS内存管理机制

retain、release、autorelease、引用计数
一个简单对象的分析
• @interface Counter : NSObject • @property (nonatomic, retain) NSNumber *count; • @end;
• - (void)setCount:(NSNumber *)newCount { • [newCount retain];// retain new object first; • [_count release]; • // Make the new assignment. • _count = newCount; •}
• release 对象引用计数-1 如果为0释放内存 • autorelease 对象引用计数-1 如果为0不马上释放,最近一个个pool
时释放
• 如果引用 计数等于0还对该对象进行操作,那么会出现内存访问失败, 造成crash,所以释放后的对象尽量设置为nil
Pool是个啥东西?
• int main (int argc, const char * argv[]) {
•
•
NSAutoreleasePool * pool = [[NSAutoreleasePool
alloc] init];
•
•
int i;
•
•
for
(i=0;i<10000;i++){
•
Sample *s = [Sample new];
•
s.flag = i;
•
NSLog(@"%@",[s toString]);
• copy
一个对象变成新的对象(新内存地址) 引用计数为1 原来对
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
原则总结
对自己拥有的对象负责 凡是你通过retain,alloc,copy等手段获得了所有权 的对象,都必须在你不再使用它的时候,由你来调用 release,autorelease等手段来释放对它的所有权 在一定的代码段内,对同一个对象所做的copy,alloc 和retain的操作次数应当与release和autorelease操作 的次数相等
Cocoa中的内存管理机制
Cocoa中提供了一个机制来实现上面提到的这个逻辑模型,它被称 为“引用计数”(referring counting)或“保留计数”(retain counting): 每一个对象都有一个引用计数(retain count) 对象被创建的时候,引用计数的值是1 当引用计数值是0的时候,对象将被系统统一销毁 retainC对象的所有权,同时放弃 旧对象的所有权
- (void) setTitle: (NSString*) newTitle { if (title != newTitle) { [title release]; title = [newTitle retain]; // or copy depending on your needs } }
示例1
使用alloc创建对象,则需要使用完毕后进行释放: - (void)printHello { NSString *string; string = [[NSString alloc] initWithString:@"Hello"]; NSLog(@”%@”,string); [string release]; }
错误3:释放了没有所有权的对象
- (void)reset { NSNumber *zero = [NSNumber numberWithInteger:0]; [self setCount:zero]; [zero release]; }
便利构造器已经为新zero设置了autorelease,Counter便没 有必要和权利再去release一次。下次你再来访问count变量 时是一定会产生运行错误的
示例2
Thingamajig *thingamajig = [[Thingamajig alloc] init]; NSArray *sprockets = [thingamajig sprockets]; [thingamajig release]; 你创建了 thingamajig对象,因为你要负责之后对它进 行释放 sprockets对象是你通过别的对象间接获取的,所以 你没有它的所有权,也不能对它进行释放
Cocoa中的内存管理机制
alloc:为一个新对象分配内存,并且它的引用计数为1。 调用alloc方法,你便有对新对象的所有权 copy:制造一个对象的副本(克隆体),该副本的引用 计数为1,调用者具有对副本的所有权 retain:使对象的引用计数加1,并且获得对象的所有权 release:使对象的引用计数减1,并且放弃对象的所有权 autorelease:使对象的引用计数在未来的某个时候减1, 并且在那个时候放弃对象的所有权
简单使用示例
使用访问器获得对象,使用完毕后也不需要进行释放: - (void)printWindowTitle { NSString *string; string = myWindow.title; NSLog(@”%@”,string); }
dealloc方法
dealloc方法在对象的引用计数为0的时候调用; 因为Counter总是一直占有一个title对象的所有权,所以 在Counter对象销毁的时候要先释放对title对象的所有权
便利构造器的内存管理
有时我们会通过便利构造器来获取一个新的对象 由便利构造器产生的对象不应当由使用者进行销毁, 而是由便利构造器自己完成 便利构造器通过在实现中使用autorelease来行使这样 的能力
便利构造器的错误实现
例1: + (Thingamajig *)thingamajig { id newThingamajig = [[Thingamajig alloc] init]; return newThingamajig; } 它是错误的,因为在返回了新创建的对象以后,类失 去了释放这个对象的机会
便利构造器的错误实现
例2: + (Thingamajig *)thingamajig { id newThingamajig = [[Thingamajig alloc] init]; [newThingamajig release]; return newThingamajig; } 例2是错误的,因为在返回对象的时候,对象已经被销 毁从而不可用了
内存管理常见错误
错误2:内存泄漏
- (void)reset { NSNumber *zero = [[NSNumber alloc] initWithInteger:0]; [self setCount:zero]; }
旧count对象的引用计数都没有得到归0就不再被使用了, 最终导致了内存泄漏
内存管理常见错误
- (void)dealloc { [title release]; [super dealloc]; }
在dealloc方法中对变量的释放顺序与初始化的顺序相 反,最后调用[super dealloc];
内存管理常见错误
错误1:未使用设置器
- (void)reset { NSNumber *zero = [[NSNumber alloc] initWithInteger:0]; count = zero; [count release]; } 注:count是一个实例变量.
内存管理
对象所有权机制 Object Ownership Policy
在Objective-C中,对象不断地被其它对象创建、使用和 销毁 为了保证程序不产生额外的内存开销,当对象不再被需 要以后,应当被立即销毁 有对一个对象的使用权称为“拥有”(own)这个对象 对象的拥有者个数至少为1,对象才得以存在,否则它 应当立即被销毁
以下是一个经典的把内存管理结合在设置器中的实现: 接口中的声明 @interface Counter : NSObject { NSString *title; }
访问器的经典实现
在访问器中,不需要进行retain或release: - (NSString *)title{ return title; }
原则总结
可以在类的dealloc方法中释放你占有的实例变量 对于遍历构造器和访问器来说,你没有通过上面的这 些手段获得的对象的所有权,因此在这些情况下你无 须对获得的对象进行额外的释放操作 autorelease只不过意味着“预定延迟发送一条release消 息”
作业
检查以前的作业有没有内存管理的问题,并改正。 SDK里面有一个Instruments工具,可以检测内存泄 露,查阅资料学习一下。
对象所有权机制
为了确定你(一个对象)何时具有对另一个对象的所有 权,以及明确对象所有者的权利和义务,Cocoa设立了一 些列的判断准则: 只有当你对一个对象做了alloc,copy或retain等操作以 后,你才拥有它的所有权 当你不再需要这个对象时,你应当释放你对它的所有权 你不可以对你没有所有权的对象执行释放操作
简单使用示例
使用便利构造器创建对象,则使用完毕后不需要进行释 放: - (void)printHello { NSString *string; string = [NSString stringWithFormat:@"Hello"]; NSLog(string); }
设置器/访问器与内存管理
便利构造器的正确实现
例3: + (Thingamajig *)thingamajig { id newThingamajig = [[Thingamajig alloc] init]; [newThingamajig autorelease]; return newThingamajig; } 例3是正确的,它把对新对象的销毁延迟进行,从而使用者 有时间去使用它,而又不必对对象的释放负责