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

#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];
}
@end

int 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值