适合有java和C基础同学迅速了解OC
- #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,未调用alloc则就也无需release
- 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;
- }
复制代码[size=17.77777862548828px]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
[size=17.77777862548828px]
@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
|