入门客AI创业平台(我带你入门,你带我飞行)
博文笔记

循环引用之【#import】【@class】和循环【retain】之【assign】

创建时间:2015-09-26 投稿人: 浏览次数:349

一、循环引用

//
//  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。