2个对象互相有着引用,A中有B,B中有A。
// 对于循环retain的情况,对象不能够释放,此时只能让一方使用assign一方使用retain,retain用于对象assign用于基本类型,assign时对cat的引用不会使cat对象计数器加1
Cat.h
#import <Foundation/Foundation.h>
@class Girl;
@interface Cat : NSObject
@property (nonatomic,copy)NSString *name;
@property (nonatomic,assign)int age;
@property (nonatomic,retain)Girl *owner; @end
Cat.m
#import "Cat.h"
@implementation Cat
- (void)dealloc
{
NSLog(@"猫被释放");
[_owner release];
[super dealloc];
}
@end Girl.h
#import <Foundation/Foundation.h>
@class Cat;
//@class Cat; // 仅仅告诉编译器cat是一个猫类,可以声明一个对象.
// 建议:以后,头文件引入一个类的时候,建议使用@class
// AimporB BimportC CimpotD:效率很低.
@interface Girl : NSObject
// 对于循环retain的情况,对象不能够释放,此时只能让一方使用assign,assign时对cat的引用不会使cat对象计数器加1
@property (nonatomic,assign)Cat *cat;
@end Girl.m
#import "Girl.h"
@implementation Girl
-(void)dealloc
{
NSLog(@"女孩被释放");
[_cat release];
[super dealloc];
}
@end main.m
#import <Foundation/Foundation.h>
#import "Girl.h"
#import "Cat.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Girl *g = [[Girl alloc] init];
Cat *c = [[Cat alloc] init];
g.cat = c; // 女孩对猫进行了一次retain,c对象计数器不加1,把c当做基本类型处理,c=1
c.owner = g; // 猫对女孩进行了一次retain,g=2
[g release];//g=1
[c release];//c=1
}
return ;
}
/*
1.@class的使用
作用
可以简单地引用一个类
简单使用
@class Dog; //类的引入,仅仅是告诉是一个类,不能用类里面的变量和方法,#import把类的变量和方法拷贝了,可以使用变量和方法
仅仅是告诉编译器:Dog是一个类;并不会包含Dog这个类的所有内容
具体使用:
在.h文件中使用@class引用一个类
在.m文件中使用#import包含这个类的.h文件 通常引用一个类有两种办法:
一种是通过#import方式引入;
另一种是通过@class引入;
这两种的方式的区别在于:
1)#import方式会包含被引用类的所有信息,包括被引用类的变量和方法;@class方式只是告诉编译器在 A.h文件中 B *b只是类的声明,具体这个类里有什么信息,这里不需要知道,等实现文件中真正要用到时,才会真正去查看B类中信息;
2)使用@class方式由于只需要知道被引用类(B类)的名称就可以了,而在实现类由于要用到被引用类中的实体变量和方法,所以需要使用#import来包含被引用类的头文件;
3)通过上面2点也很容易知道在编译效率上,如果有上百个头文件都#import了同一个文件,或者这些文件依次被#improt(A->B, B->C,C->D...),一旦最开始的头文件稍有改动,后面引用到这个文件的所有类 都需要重新编译一遍,这样的效率也是可想而知的.而相对来讲,使用@class方式就不会出现这种问题了;
所以:我们实际开发中尽量在.h头文件中使用@class
*/