循环引用之【#import】【@class】和循环【retain】之【assign】
一、循环引用
// // Person.h // OCStudy // // Created by LiuMingchuan on 15/9/26. // Copyright © 2015年 LMC. All rights reserved. // #import <Foundation/Foundation.h> #import "Dog.h" @interface Person : NSObject @property (nonatomic,retain) Dog *dog; @end
// // Person.m // OCStudy // // Created by LiuMingchuan on 15/9/26. // Copyright © 2015年 LMC. All rights reserved. // #import "Person.h" @implementation Person @end
// // Dog.h // OCStudy // // Created by LiuMingchuan on 15/9/26. // Copyright © 2015年 LMC. All rights reserved. // #import <Foundation/Foundation.h> #import "Person.h" @interface Dog : NSObject @property (nonatomic,retain) Person *master; @end
// // Dog.m // OCStudy // // Created by LiuMingchuan on 15/9/26. // Copyright © 2015年 LMC. All rights reserved. // #import "Dog.h" @implementation Dog @end
上面的两个类中,Person和Dog互相引用,在编译时会造成循环引用,使得编译不能通过。
但是我们经常会有这样的使用要求,两个类中互相引用
就像上面写的【主人有一只狗】、【狗有主人】
这时我们就可以在【.h】文件中不用import的形式将类的内容全部导入,我们使用@class
@class的作用是单纯的告诉编译器,后面的名字指示的是一个类,但是并不将类的内容导入
如下
// // Person.h // OCStudy // // Created by LiuMingchuan on 15/9/26. // Copyright © 2015年 LMC. All rights reserved. // #import <Foundation/Foundation.h> //#import "Dog.h" @class Dog; @interface Person : NSObject @property (nonatomic,retain) Dog *dog; @end
// // Dog.h // OCStudy // // Created by LiuMingchuan on 15/9/26. // Copyright © 2015年 LMC. All rights reserved. // #import <Foundation/Foundation.h> //#import "Person.h" @class Person; @interface Dog : NSObject @property (nonatomic,retain) Person *master; @end通过上面使用@class之后就可以正常编译了。
因为在【.h】文件中我们指示声明它是一个类,当我们真正使用的时候,因为不像import,并没有把类的所有内容拷贝过去,所以我们在实现的文件中无法使用,这就需要我们在【.m】文件中,再#import一下我们需要的文件
// // Person.h // OCStudy // // Created by LiuMingchuan on 15/9/26. // Copyright © 2015年 LMC. All rights reserved. // #import <Foundation/Foundation.h> //#import "Dog.h" @class Dog; @interface Person : NSObject @property (nonatomic,retain) Dog *dog; - (void)print; @end
不可用:
可用:
注意点:
使用import:当我们的A.h被其他N多个类文件使用的时候,当我们的A.h做了变更,会让其他N多个类都会重新拷贝,会使得编译时性能下降
但是当我们使用@class时,则不会有上面的问题,从而使得编译效率提高;
所以在所有的【.h】文件中我们不要使用import,我们要使用@class
二、循环retain
// // Person.h // OCStudy // // Created by LiuMingchuan on 15/9/26. // Copyright © 2015年 LMC. All rights reserved. // #import <Foundation/Foundation.h> @class Dog; @interface Person : NSObject @property (nonatomic,retain) Dog *dog; - (void)print; @end
// // Person.m // OCStudy // // Created by LiuMingchuan on 15/9/26. // Copyright © 2015年 LMC. All rights reserved. // #import "Person.h" #import "Dog.h" @implementation Person -(void)print{ NSLog(@"%@",[_dog master]); } -(void)dealloc{ [_dog release]; NSLog(@"Person释放"); [super dealloc]; } @end
// // Dog.h // OCStudy // // Created by LiuMingchuan on 15/9/26. // Copyright © 2015年 LMC. All rights reserved. // #import <Foundation/Foundation.h> //#import "Person.h" @class Person; @interface Dog : NSObject @property (nonatomic,retain) Person *master; @end
// // Dog.m // OCStudy // // Created by LiuMingchuan on 15/9/26. // Copyright © 2015年 LMC. All rights reserved. // #import "Dog.h" @implementation Dog -(void)dealloc{ [_master release]; NSLog(@"Dog释放"); [super dealloc]; } @end
1⃣️
// // main.m // OCStudy // // Created by LiuMingchuan on 15/9/24. // Copyright © 2015年 LMC. All rights reserved. // #import <Foundation/Foundation.h> #import "Person.h" #import "Dog.h" int main(int argc, const char * argv[]) { Person *person = [[Person alloc]init];//person-指针引用计数 1 Dog *dog = [[Dog alloc]init];//dog-指针引用计数 1 [dog release];//dog-指针引用计数 0 [person release];//person-指针引用计数 0 return 0; }
输出:
2015-09-26 21:20:24.908 OCStudy[5905:4226875] Dog释放 2015-09-26 21:20:24.909 OCStudy[5905:4226875] Person释放
2⃣️
// // main.m // OCStudy // // Created by LiuMingchuan on 15/9/24. // Copyright © 2015年 LMC. All rights reserved. // #import <Foundation/Foundation.h> #import "Person.h" #import "Dog.h" int main(int argc, const char * argv[]) { Person *person = [[Person alloc]init];//person-指针引用计数 1 Dog *dog = [[Dog alloc]init];//dog-指针引用计数 1 person.dog = dog;//person-指针引用计数 2 dog.master = person;//person-指针引用计数 2 [dog release];//dog-指针引用计数 1 [person release];//person-指针引用计数 1 return 0; }输出:
2⃣️中我们看到并没有输出任何的信息,说明没有释放掉对象,原因就是因为我们的retain循环引用
// // Person.h // OCStudy // // Created by LiuMingchuan on 15/9/26. // Copyright © 2015年 LMC. All rights reserved. // #import <Foundation/Foundation.h> @class Dog; @interface Person : NSObject @property (nonatomic,retain) Dog *dog; - (void)print; @end
// // Dog.h // OCStudy // // Created by LiuMingchuan on 15/9/26. // Copyright © 2015年 LMC. All rights reserved. // #import <Foundation/Foundation.h> //#import "Person.h" @class Person; @interface Dog : NSObject @property (nonatomic,retain) Person *master; @end
相互引用都使用了retain,谁都不放开谁
解决方案:一方使用retain另一方使用assign
注意:因为assign是直接赋值,对应的使用assign的一方不必再对变量进行release(在dealloc中使用release)
下面我们对Dog的mster属性使用assign
// // Dog.h // OCStudy // // Created by LiuMingchuan on 15/9/26. // Copyright © 2015年 LMC. All rights reserved. // #import <Foundation/Foundation.h> //#import "Person.h" @class Person; @interface Dog : NSObject //@property (nonatomic,retain) Person *master; @property (nonatomic,assign) Person *master; @end
// // Dog.m // OCStudy // // Created by LiuMingchuan on 15/9/26. // Copyright © 2015年 LMC. All rights reserved. // #import "Dog.h" #import "Person.h" @implementation Dog -(void)dealloc{ // [_master release]; NSLog(@"Dog释放"); [super dealloc]; } @end输出:
2015-09-26 21:31:32.641 OCStudy[5940:4285480] Dog释放 2015-09-26 21:31:32.643 OCStudy[5940:4285480] Person释放
总结:
1⃣️在类文件的【.h】中,我们使用【@class】进行类的声明,在【.m】中,我们使用【#import】进行类的引用
2⃣️在类文件相互拥有的场合,对于变量的声明,我们一方使用retain,一方使用assign,从而避免循环retain
声明:该文观点仅代表作者本人,入门客AI创业平台信息发布平台仅提供信息存储空间服务,如有疑问请联系rumenke@qq.com。
- 上一篇: PHP限制上传文件的大小(修改PHP.ini)
- 下一篇: BAT执行PHP