OC学习笔记07--OC中内存管理与循环retain问题

来源:互联网 发布:淘宝大学官方网站 编辑:程序博客网 时间:2024/06/10 12:17
#import <Foundation/Foundation.h>//告诉编译器ClassB是一个类@class ClassB;//ClassA@interface ClassA : NSObject{ClassB *_b;}- (void)setB:(ClassB *)b;@property (nonatomic,retain,readwrite) NSString *name;@property (nonatomic,assign) int count;@end@implementation ClassA //重写对象销毁的方法,该方法为系统销毁对象时调用,不要手动调用- (void)dealloc{NSLog(@"%@ dealloc",[self className]);//销毁方法中释放对象资源[_b release];[_name release];//super一定要调用,且最后调用[super dealloc];}- (void)setB:(ClassB *)b{if(_b!=b){[_b release]; //OC中对空指针调用方法不报错_b=[b retain]; //先retain再赋值}}@end//ClassB@interface ClassB : NSObject{ClassA *_a;}- (void)setA:(ClassA *)a;@property (nonatomic,retain) NSObject *obj;// 一般成员变量是BOOL类型时,getter名字以is开头@property (nonatomic,assign,getter=isBusy) BOOL busy;@end@implementation ClassB- (void)setA:(ClassA *)a{//两个对象互相引用的情况下,为防止发生//循环retain导致都无法销毁的情况,//set方法中一方使用retain形式,一方使用assign形式_a=a;}- (void)dealloc{//由于set方法中并未对_a进行retain,dealloc中也不需要进行release//否则可能产生野指针错误//[_a release];NSLog(@"%@ dealloc",[self className]);[_obj release];[super dealloc];}@endint main(){ClassA * a = [[ClassA alloc] init];NSUInteger c=[a retainCount];//retainCount返回 unsigned long类型,使用%ld输出NSLog(@"Acount=%ld",c);ClassB *b=[[ClassB alloc] init];[b setA:a],[a setB:b];// OC字符串常量无需手动release,此种方式返回的OC字符串是autorelease过的NSString * name=@"ClassA_Name";[a setName:name];NSObject *obj=[[NSObject alloc] init];[b setObj:obj];[b setBusy:YES];BOOL busy;// getter设为isBusy后,仍然可以通过busy来调用该getter,//这时[b busy]  b.busy 与 [b isBusy]  b.isBusy 是等价的//编译器会自动将 b.busy 转换成 [b isBusy]busy=[b busy];busy=[b isBusy];[obj release];[a release];[b release];return 0;}





OC中野指针错误:EXC_BAD_ACCESS
若指针指向的内存已经被回收(成为僵尸对象),即不可用,操作该内存区域就会产生野指针错误
OC中不存在空指针错误,给空指针发送消息,不报错


NSObject中内存管理相关方法:
retain 方法返回对象本身  计数器+1
release 计数器-1
retainCount  返回计数器的值




内存管理原则:
1>方法结束前把该方法中所有赋值给方法中局部变量的alloc的
对象release (由alloc后赋值给的变量来release)
---OC字符串常量@"XXX"形式,无alloc则也无需release
2>set对象方法中,判断传入的对象与成员是否是同一个对象,
如果不是则先释放原对象,在将新传入的对象retain后赋值
3>对象销毁时对成员引用的其他对象调用release,即在对象dealloc方法
中释放其成员中引用的对象,由retain后赋值给的变量来release
    


@property参数:  (同种类型参数只能写一个)
1>内存管理相关:
retain  (适用于OC对象)   
assign(default 直接赋值,使用非OC对象类型)  
copy(release旧值,copy新值)
2>getter,setter生成相关:
readonly  
readwrite(default) 
3>多线程管理:
nonatomic(不加同步锁,性能高,无特殊情况均需要使用此参数)  
atomic(default 加同步锁)
4>getter和setter方法名:
setter=setXX: (setter方法名必须以:结尾)    
getter=XXX
例:@property(nonatomic,retain,readwrite,getter=name,setter=setName:) NSObject * obj;


循环#import用与@class:  (@class XXX 告诉编译器XXX是个OC类)
A类中包含B类,B类中包含A类,头文件中使用#import命令就会发生
循环引用问题(头文件中互相引入导致死循环);
解决方法:.h文件中利用@class关键字引用类型,.m文件中再#import 对方类的头文件
为提高编译效率,.h文件中除了父类头文件需要#import,
其他类型最好都使用@class来声明,.m文件中再#import


循环retain:
A类与B类互相引用,setter使用正常的retain的话,
会导致双方互相引用后都无法正常dealloc
解决方法:此种情况,一方setter使用retain,另一方setter使用assign







0 0