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 0; }
/* 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 */