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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

一、@class的使用方法
1、使用
【@import】会把引用的头文件整个拷贝到@import的使用处
如果该头文件改变了,那么所有引用它的文件都需要重新编译,导致效率非常低

【@class的使用】
格式:@class XXX;
【含义】告诉编译器,XXX是一个类,至于类有哪些方法和属性,此处不去检测。
【好处】如果XXX文件内容发生了改变,而不需要重新编译
【缺点】因为无法检测到引入类的方法和属性,因此也无法访问。
【解决方法】因为编译时先编译.h头文件,因此在.h头文件中使用@class告知有要引入的类,.m文件是在运行时编译,因此可以在.m文件中使用#import指定的头文件,这样只有程序运行的时候才去检查,然后重新编译,可以极大地提高效率。
【注意】
1).h @class 类名;
2).m #import 类名;

2、@class可以解决循环引入问题
例如:
有A、B两个类,如果在A类头文件中使用#import引入了B,又在B类头文件中使用#import引入了A,这样在就会报错。
【解决方案】在两个类的头文件中使用@class引入对方的类名


二、循环retain问题
1、循环retain的问题
会导致两个对象的内存泄露
【解决方案】
1)让某个对象多释放一次,(注意顺序)
2)【推荐方法】一端使用assign一端使用retain

例子:
【人有一条狗,狗有一个主人】
【Person.h文件】
  1. #import <Foundation/Foundation.h>
  2. @class Dog;

  3. @interface Person : NSObject{
  4.     //人拥有一条狗,使用的是retain
  5.     Dog *_dog;
  6. }
  7. @property(nonatomic,retain) Dog *dog;
  8. @end
复制代码

【Person.m文件】
  1. #import "Person.h"
  2. #import "Dog.h"
  3. @implementation Person
  4. -(void)dealloc{
  5.    
  6.     //人死前先把狗放了
  7.     [_dog release];
  8.     NSLog(@"This person dead....");
  9.     [super dealloc];
  10. }
  11. @end
复制代码


【Dog.h文件】
  1. #import <Foundation/Foundation.h>
  2. @class Person;
  3. @interface Dog : NSObject{
  4.     //狗有一个主人,使用retain
  5.     Person *_p;
  6. }
  7. @property(nonatomic,retain) Person *p;
  8. @end
复制代码


【Dog.m文件】
  1. #import "Dog.h"
  2. #import "Person.h"
  3. @implementation Dog
  4. -(void)dealloc{
  5.     //狗跑之前先把主人咬死
  6.     [_p release];
  7.     NSLog(@"The dog is gone....");
  8.     [super dealloc];
  9. }
  10. @end
复制代码

【main.m文件】
  1. #import <Foundation/Foundation.h>
  2. #import "Person.h"
  3. #import "Dog.h"

  4. int main(int argc, const char * argv[])
  5. {

  6.     @autoreleasepool {
  7.         //实例化一个person对象
  8.         Person *p = [Person new]; //p的计数器值 1
  9.         Dog *dog = [Dog new];//dog的计数器值 1
  10.         
  11.         p.dog = dog;//dog的计数器值 2
  12.         
  13.         dog.p = p;//p的计数器值 2
  14.         
  15.         [dog release];//dog的计数器值 1
  16.         [p release];//p的计数器值 1
  17.     }

  18.     return 0;
  19. }
复制代码

【结果分析】
最后dog和p的计数器值都为1.最后两个对象的堆区内存都没有被释放,导致了内存泄露。
【误区】
一开始我认为在delloc方法中,两个对象不都把拥有的对象给release掉了么?怎么也想不明白为什么最后计数器值都为1。最后终于明白了,只要记住一点【delloc只有在一个对象的计数器值为0的时候由系统自动调用的】就行了。这样是不是就明白了呢?

【解决方法1】任何一个对象多释放一次,不过这样需要注意顺序,具体需要计算他们的计数器值
  1.         [dog release];//dog的计数器值 1
  2.         [p release];//p的计数器值 1
  3. [p release];//p的计数器值 1
复制代码


【解决方法2:墙裂推荐】一端使用assign一端使用retain
只要把
Dog.h文件中的属性改为
  1. @property(nonatomic,assign) Person *p;
复制代码
Dog.m文件中的方法改为
  1. -(void)dealloc{
  2.     NSLog(@"The dog is gone....");
  3.     [super dealloc];
  4. }
复制代码


此时打印结果:
2015-10-06 15:31:53.418 MRCDemo[1967:303] The god isgone....
2015-10-06 15:31:53.420 MRCDemo[1967:303] This persondead....

0 个回复

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