#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