A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

适合有java和C基础同学迅速了解OC

  1. #import <Foundation/Foundation.h>

  2. //告诉编译器ClassB是一个类
  3. @class ClassB;



  4. //ClassA
  5. @interface ClassA : NSObject
  6. {
  7.         ClassB *_b;
  8. }
  9. - (void)setB:(ClassB *)b;

  10. @property (nonatomic,retain,readwrite) NSString *name;

  11. @property (nonatomic,assign) int count;

  12. @end

  13. @implementation ClassA

  14. //重写对象销毁的方法
  15. - (void)dealloc
  16. {
  17.         NSLog(@"%@ dealloc",[self className]);
  18.         //销毁方法中释放对象资源
  19.         [_b release];
  20.         [_name release];
  21.         //super一定要调用,且最后调用
  22.         [super dealloc];
  23. }
  24. - (void)setB:(ClassB *)b
  25. {
  26.         if(_b!=b)
  27.         {
  28.                 [_b release]; //OC中对空指针调用方法不报错
  29.                 _b=[b retain]; //先retain再赋值
  30.         }
  31. }

  32. @end




  33. //ClassB
  34. @interface ClassB : NSObject
  35. {
  36.         ClassA *_a;
  37. }

  38. - (void)setA:(ClassA *)a;

  39. @property (nonatomic,retain) NSObject *obj;


  40. // 一般成员变量是BOOL类型时,getter名字以is开头
  41. @property (nonatomic,assign,getter=isBusy) BOOL busy;

  42. @end

  43. @implementation ClassB


  44. - (void)setA:(ClassA *)a
  45. {
  46.         //两个对象互相引用的情况下,为防止发生
  47.         //循环retain导致都无法销毁的情况,
  48.         //set方法中一方使用retain形式,一方使用assign形式
  49.         _a=a;
  50. }

  51. - (void)dealloc
  52. {
  53.         //由于set方法中并未对_a进行retain,dealloc中也不需要进行release
  54.         //否则可能产生野指针错误
  55.         //[_a release];
  56.         NSLog(@"%@ dealloc",[self className]);
  57.         
  58.         [_obj release];
  59.         [super dealloc];
  60. }
  61. @end

  62. int main()
  63. {
  64.         ClassA * a = [[ClassA alloc] init];
  65.         NSUInteger c=[a retainCount];
  66.         //retainCount返回 unsigned long类型,使用%ld输出
  67.         NSLog(@"Acount=%ld",c);
  68.         
  69.         ClassB *b=[[ClassB alloc] init];
  70.         
  71.         [b setA:a],[a setB:b];
  72.         
  73.         
  74.         // OC字符串常量无需手动release,未调用alloc则就也无需release
  75.         NSString * name=@"ClassA_Name";
  76.         [a setName:name];
  77.         NSObject *obj=[[NSObject alloc] init];
  78.         [b setObj:obj];
  79.         [b setBusy:YES];
  80.         BOOL busy;
  81.         // getter设为isBusy后,仍然可以通过busy来调用该getter,
  82.         //这时[b busy]  b.busy 与 [b isBusy]  b.isBusy 是等价的
  83.         //编译器会自动将 b.busy 转换成 [b isBusy]
  84.         busy=[b busy];
  85.         busy=[b isBusy];
  86.         
  87.         
  88.         [obj release];
  89.         [a release];
  90.         [b release];
  91.         return 0;
  92. }
复制代码

[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






0 个回复

您需要登录后才可以回帖 登录 | 加入黑马