- 不要等到明天,明天太遥远,今天就行动。
须读:看完该文章你能做什么?
能够管理好多个类之间的内存管理,学习一些逼格的代码
学习前:你必须会什么?(在这里我已经默认你具备C语言的基础了)
什么是类,
怎么实现setter/getter方法(内存管理下).
@property关键字的修饰符的<内部实现>是如何处理setter/getter方法的
一、本章笔记
项目1
一、import
#import "Car.h" == 下面的代码
#import <Foundation/Foundation.h>
@interface Car : NSObject
@end
由于import 是一个预编译指令,他会将""中的文件拷贝所在的位置
并且import 有一个特点, 只要""中的文件发送了变化,那么import就会重新拷贝(更新操作)
二、@class
@class 仅仅告诉编译器,@class后面的名称是一个类,不会做任何拷贝操作
注意 : 由于 class 仅仅是告诉编译器 后面的名称是一个类,所以编译器并不知道这个类中 有哪些属性和方法,所以在.m 中使用这个类时 需要import 这个类,才能使用
总结:
1.如果都在.h中import,假如A拷贝了B,B拷贝了C,如果C被修改了,那么B和A都需要重新拷贝.因为C修改了,那么B就会重新拷贝,而B重新拷贝之后 相当于B也被修改了,那么A也需要重新拷贝.也就是说, 如果都在.h中拷贝, 只要有间接关系 都会重新拷贝
2.如果在.h用 @class , 在.m用import,那么如果一个文件发生了变化,只有和这个文件有直接关系的那个文件 才会重新拷贝
3.所以在 .h 用@class 可以提升编译效率
项目2
总结:
如果两个类相互拷贝,例如A拷贝B,B拷贝B,这样会报错
如何解决 : 在.h中用@class,在.m中用import
因为如果.h都用import, 那么A拷贝B, B拷贝A,会形成死循环
如果在.h 中 用@class,那么不会做任何拷贝操作,而在.m用import只会拷贝对应的文件,并不会形成死循环
二、项目1
main.m
#pragma mark 10-@class
#pragma mark 概念
/*
一、import
#import "Car.h" == 下面的代码
#import <Foundation/Foundation.h>
@interface Car : NSObject
@end
由于import 是一个预编译指令,他会将""中的文件拷贝所在的位置
并且import 有一个特点, 只要""中的文件发送了变化,那么import就会重新拷贝(更新操作)
二、@class
@class 仅仅告诉编译器,@class后面的名称是一个类,不会做任何拷贝操作
注意 : 由于 class 仅仅是告诉编译器 后面的名称是一个类,所以编译器并不知道这个类中 有哪些属性和方法,所以在.m 中使用这个类时 需要import 这个类,才能使用
总结:
1.如果都在.h中import,假如A拷贝了B,B拷贝了C,如果C被修改了,那么B和A都需要重新拷贝.因为C修改了,那么B就会重新拷贝,而B重新拷贝之后 相当于B也被修改了,那么A也需要重新拷贝.也就是说, 如果都在.h中拷贝, 只要有间接关系 都会重新拷贝
2.如果在.h用 @class , 在.m用import,那么如果一个文件发生了变化,只有和这个文件有直接关系的那个文件 才会重新拷贝
3.所以在 .h 用@class 可以提升编译效率
*/
#pragma mark - 代码
#import <Foundation/Foundation.h>
#pragma mark 类
#pragma mark - main函数
int main(int argc, const char * argv[])
{
return 0;
}
Person
>>>.h
#import <Foundation/Foundation.h>
//#import "Car.h"
/*
#import "Car.h" == 下面的代码
#import <Foundation/Foundation.h>
@interface Car : NSObject
@end
*/
/*
由于import 是一个预编译指令,他会将""中的文件拷贝所在的位置
并且import 有一个特点, 只要""中的文件发送了变化,那么import就会重新拷贝(更新操作)
*/
@class Car;
/*
@class 仅仅告诉编译器,@class后面的名称是一个类,不会做任何拷贝操作
注意 : 由于 class 仅仅是告诉编译器 后面的名称是一个类,所以编译器并不知道这个类中 有哪些属性和方法,所以在.m 中使用这个类时 需要import 这个类,才能使用
*/
@interface Person : NSObject
@property (nonatomic,retain) Car *car;
@end
>>>.m
#import "Person.h"
#import "Car.h"
@implementation Person
- (void)dealloc
{
[_car release];
[super dealloc];
}
@end
Car
>>>.h
#import <Foundation/Foundation.h>
//#import "Wheel.h"
@class Wheel;
@interface Car : NSObject
@property (nonatomic,retain) Wheel *wheel;
@end
>>>.m
#import "Car.h"
#import "Wheel.h"
@implementation Car
- (void)dealloc
{
[_wheel release];
[super dealloc];
}
@end
Wheel
>>>.h
#import <Foundation/Foundation.h>
@interface Wheel : NSObject
@property (nonatomic,assign) int size;
@end
>>>.m
#import "Wheel.h"
@implementation Wheel
@end
三、项目2
main.m
#pragma mark 10-@class应用场景
#pragma mark 概念
/*
总结:
如果两个类相互拷贝,例如A拷贝B,B拷贝B,这样会报错
如何解决 : 在.h中用@class,在.m中用import
因为如果.h都用import, 那么A拷贝B, B拷贝A,会形成死循环
如果在.h 中 用@class,那么不会做任何拷贝操作,而在.m用import只会拷贝对应的文件,并不会形成死循环
*/
#pragma mark - 代码
#import <Foundation/Foundation.h>
#pragma mark 类
#import "Person.h"
#import "Dog.h"
#pragma mark - main函数
int main(int argc, const char * argv[])
{
Person *p = [Person new];
Dog *d = [Dog new];
p.dog = d;
[p release];
[d release];
return 0;
}
Person
>>>.h
#import <Foundation/Foundation.h>
//#import "Dog.h"
@class Dog;
/*
总结:
如果两个类相互拷贝,例如A拷贝B,B拷贝B,这样会报错
如何解决 : 在.h中用@class,在.m中用import
因为如果.h都用import, 那么A拷贝B, B拷贝A,会形成死循环
如果在.h 中 用@class,那么不会做任何拷贝操作,而在.m用import只会拷贝对应的文件,并不会形成死循环
*/
@interface Person : NSObject
@property (nonatomic,retain) Dog *dog;
@end
>>>.m
#import "Person.h"
#import "Dog.h"
@implementation Person
- (void)dealloc
{
NSLog(@"%s",__func__);
[_dog release];
[super dealloc];
}
@end
Dog
>>>.h
#import <Foundation/Foundation.h>
//#import "Person.h"
@class Person;
@interface Dog : NSObject
@property (nonatomic,retain) Person *owner; // Unkown type name Person
@end
>>>.m
#import "Dog.h"
#import "Person.h"
@implementation Dog
- (void)dealloc
{
NSLog(@"%s",__func__);
[_owner release];
[super dealloc];
}
@end
一、使用import
造成循环拷贝
二、使用@class
解决循环拷贝