一、循环引用
//
// 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