内存储器管理和特性
内存管理和特性
#import <Foundation/Foundation.h> #import "RetainTracker.h" /** 不用使用任何刚释放的内存,否则我们将可能误用陈旧的数据,从而引起各种各样的错误,而如果该内存已经加载了其他数据,我们将破坏这些数据 对象的生命周期包括诞生(通过alloc或new方法实现),生存(接受消息和执行操作),交友(借助方法的组合和参数)以及当它们的生命结束时最终死去(被释放) cocoa采用了一种成为引用计数的技术,有时也叫保留计数。每个对象有一个与之相关联的整数,称作它的引用计数器或者保留计数器。当某段代码需要访问一个对象时,该代码将该对象的保留计数器值加1,表示‘我要访问该对象’ 当这段代码结束对象访问时,将对象的保留计数器值减1,表示它不再访问该对象。 当使用alloc,new方法或者copy消息创建一个对象时,对象的保留计数器值被设置为1,要增加对象的保留计数器值,可以给对象发送一条retain信息。要减少对象的保留计数器值,可以给对象发送一条release信息。 当一个对象因其计数器归0而即将被销毁时,objective-c自动向对象发送一条dealloc消息,你可以在自己的对象中重写dealloc方法,可以通过这种方法释放已经分配的全部相关资源。一定不要直接调用dealloc方法。 可以利用objective-c在需要销毁对象时调用deallocff。 要获取对象的保留计数器的当前值,可以发送retainCount信息。 -(id) retain;--retain方法返回一个id类型的值,通过这种方式,可以嵌套执行带有其他信息发送参数的保留调用,增加对象的保留计数器值并要求对象完成某种操作,例如:[[car retain] setTire:tire atIndex:2]] -(void) release; -(unsinged) retainCount; */ int main (int argc, const char * argv[]) { //cocoa中有一个自动释放池的概念,它是一个存放实体的池,这些实体可能是对象,能够被自动释放 /* NSObject 提供了一个autorelease方法 -(id) autorelease; 该方法预先设定了一个着将来某个时间发送的release信息,其返回值是接收消息的对象。 retain消息采用了相同的机制,使嵌套调用更加容易。当给一个对象发送autorelease信息时,实际上上将该对象添加到NSAutoreleasePool中。当自动释放池被销毁时,会向该池中的所有对象方法release消息。 **/ NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; //对象初始化 /* *创建对象到两种方法:1:[类名 new] 2:[[类名 alloc] init] 着两种方法是等价到,不过一般习惯用第二种方法 * */ RetainTracker *track=[RetainTracker new]; /* alloc 分配对象 从操作系统中获得一块内存并将其指定为存放对象到实例变量到位置 init 初始化对象 从操作系统中取得一块内存,准备用于存储对象。init方法几乎总是返回它们正在初始化到对象。 **/ //RetainTracker *t=[[RetainTracker alloc] init]; NSLog(@"1==%d",[track retainCount] ); [track retain]; NSLog(@"2===%d",[track retainCount]); [track release]; NSLog(@"3==%d",[track retainCount]); //drain方法只是清空自动释放池,而不销毁它,只适用于高版本 //[pool releas]; [pool drain]; return 0; } /** 当我们说某个实体“拥有一个对象”时就意味着该实体负责确保对其拥有的对象进行清理。 如果一个对象具有指向其他对象的实例变量,则称该对象拥有这些对象 访问方法里的保留和释放-------先保留新对象,然后再释放旧对象, -(void) setTire:(Engine *) newEngine{ [newEngine retain]; [engine release]; engine=newEngine; } */ /** cocoa的内存管理规则 1:当使用new,alloc,或者copy方法创建一个对象时,该对象的保留计数器值为1.当不再使用该对象时,你要负责向该对象发送一条release或autorelease消息。 2:当通过任何其他方法获得一个对象时,则假设该对象的保留计数器值为1,且已经被设置为自动释放,你不需要执行任何操作来确保对象被清楚。如果你打算在一段时间内拥有该对象,则需要保留它并确保在操作完成时释放它 3:如果你保留了某个对象,你需要最终释放或自动释放该对象,必须保持retain方法和release方法的使用次数相等。 */ /** 自动释放池被清楚的时间是完全确定的,要么是在你自己的代码中显示地销毁,要么是在事件循环结束时使用appkit销毁。你不必关系守护程序任何随机地销毁自动释放池。因为在调用函数到过程中自动释放池不会被销毁,所以你 也不必保留使用到每一个对象 **///
// RetainTrackr.h // MemoryManager // // Created by 110 on 10-1-24. // Copyright 2010 __MyCompanyName__. All rights reserved. // #import <Cocoa/Cocoa.h> @interface RetainTracker : NSObject { float rain; float snow; } //特性 // @property 预编译指令的作用所自动声明属性的setter和getter方法。实际上属性的名称不必和实例变量的名称相同,但大多数情况下它们是一样的 @property float rain; @property float snow; //特性的扩展 /** retain:保留 readonly:只读,只生成getter方法 copy:复制 nonatomic:不生成多线程代码 readwrite:默认属性,可读写的 */ //@property (retain,readonly,copy,) float rain; @end
//
// RetainTrackr.m // MemoryManager // // Created by 110 on 10-1-24. // Copyright 2010 __MyCompanyName__. All rights reserved. // #import "RetainTracker.h" @implementation RetainTracker //特性 //@synthesize 也是一种新的编译器功能,表示“创建该属性的访问器” @synthesize rain; @synthesize snow; //init方法遵循标准的cocoa对象初始化方式 /* init方法应该完成那些工作??? 在该方法中,你要执行全新到初始化工作,给实例变量赋值并创建你到对象完成任务所需要到其他对象。 ***/ - (id) init { //[super inti]----使超类完成它们自己到初始化工作 /** 实例变量所在到内存位置到隐藏到self参数之间到距离使固定到。如果从init方法返回一个新对象,则需要更新self,以便其后到任何实例变量到引用可以被映射到正确到内存位置。这也是我们需要使用self=[super init]形式进行赋值到原因。 这个赋值操作只影响init方法中self到值,而不影响该方法范围以外到任何内存 */ self = [super init]; //如果在初始化一个对象时出现问题,则init方法可能返回nil if (self != nil) { NSLog(@"init : retain count of %d",[self retainCount]); } //init方法返回已经被初始化到对象 return self; } /** 指定初始化函数: 类中到某个初始化方法被指派为指定初始化函数,该类的所有初始化方法使用指定初始化函数执行初始化操作。子类使用其超类的指定初始化函数实现超类的初始化。通常接收参数最多的初始化方法最终成为指定 初始化函数。 ***/ //重写dealloc方法,在对象的保留计数器值为0的时候objective-c会自动调用该方法以释放分配的资源,(千万不要手动调用) - (void) dealloc { NSLog(@"dealloc called bye bye"); [super dealloc]; } //重写description方法,构造自己的说明字符串,该方法着nslog()时自动调用 -(NSString *) description { //initWithFormat:便利初始化函数 NSString *description=[[NSString alloc] initWithFormat:@"ssssssssss"]; //把description字符串放入自动释放池, return [description autorelease]; } @end
//
// RetainTrackCategory.h // MemoryManager // // Created by 110 on 10-1-26. // Copyright 2010 __MyCompanyName__. All rights reserved. // #import <Cocoa/Cocoa.h> // 类名 类别命 @interface RetainTrack (RetainTrackCategory) /* 类别的声明中没有实例变量部分,只能声明消息 */ -(NSString *) print; @end /** 类别的局限性 1:无法向类别中添加新的实例变量。类别没有位置容纳实例变量 2:名称冲突,即类别中的方法与现有的方法重名。当发送方法名称冲突时,类别具有更高的优先级。你的类别方法将完全取代初始化方法,从而无法再使用初始方法。 类别的作用 1:使用类别分散实现 在使用一个对象时,对象的方法是在接口中声明,在父类中声明还是在类别中声明并不重要。 2:使用类别创建前向引用 */ /** 委托(delegate),委托是一种对象,另一个对象会要求委托对象执行它的某些操作。 委托和类别 :委托强调类别的另一种应用:被发送给委托对象的方法可以声明为一个NSObject的类别, 创建一个NSObject的类别成为“创建一个非正式协议”,使用非正式协议,你可以只实现你想要的方法。 */ /*** 响应选择器 什么所选择器:选择器只是一个方法名称,但它以objective-c运行时使用的特殊方法编码,以快速执行查询。你可以使用@selector()预编译指令指定选择器,其中方法名位于圆括号中。 NSObject 提供了一个名为respondsToSelector:的方法,该方法询问对象以确定其是否能够响应某个特定的消息。 if([car respondsToSelector:@selector(setEngine:)]{ NSLog(@"ssssss"); } 选择器可以被传递,可以作为方法的参数使用,甚至可以作为实例变量存储 */
//
// RetainTrackCategory.m // MemoryManager // // Created by 110 on 10-1-26. // Copyright 2010 __MyCompanyName__. All rights reserved. // #import "RetainTrackCategory.h" /** 类别:是一种为现有的类添加新方法的方式。 只有保证类别名称的唯一性,你可以向一个类添加任意多的类别 */ @implementation RetainTrackCategory (RetainTrackCategory) -(NSString *) print{ NSLog(@"pring-------"); } @end