一、@class的使用方法 1、使用 【@import】会把引用的头文件整个拷贝到@import的使用处 如果该头文件改变了,那么所有引用它的文件都需要重新编译,导致效率非常低
【@class的使用】 格式:@class XXX; 【含义】告诉编译器,XXX是一个类,至于类有哪些方法和属性,此处不去检测。 【好处】如果XXX文件内容发生了改变,而不需要重新编译 【缺点】因为无法检测到引入类的方法和属性,因此也无法访问。 【解决方法】因为编译时先编译.h头文件,因此在.h头文件中使用@class告知有要引入的类,.m文件是在运行时编译,因此可以在.m文件中使用#import指定的头文件,这样只有程序运行的时候才去检查,然后重新编译,可以极大地提高效率。 【注意】 1).h @class 类名; 2).m #import 类名;
2、@class可以解决循环引入问题 例如: 有A、B两个类,如果在A类头文件中使用#import引入了B,又在B类头文件中使用#import引入了A,这样在就会报错。 【解决方案】在两个类的头文件中使用@class引入对方的类名
二、循环retain问题 1、循环retain的问题 会导致两个对象的内存泄露 【解决方案】 1)让某个对象多释放一次,(注意顺序) 2)【推荐方法】一端使用assign一端使用retain
例子: 【人有一条狗,狗有一个主人】 【Person.h文件】 - #import <Foundation/Foundation.h>
- @class Dog;
-
- @interface Person : NSObject{
- //人拥有一条狗,使用的是retain
- Dog *_dog;
- }
- @property(nonatomic,retain) Dog *dog;
- @end
复制代码
【Person.m文件】- #import "Person.h"
- #import "Dog.h"
- @implementation Person
- -(void)dealloc{
-
- //人死前先把狗放了
- [_dog release];
- NSLog(@"This person dead....");
- [super dealloc];
- }
- @end
复制代码
【Dog.h文件】 - #import <Foundation/Foundation.h>
- @class Person;
- @interface Dog : NSObject{
- //狗有一个主人,使用retain
- Person *_p;
- }
- @property(nonatomic,retain) Person *p;
- @end
复制代码
【Dog.m文件】 - #import "Dog.h"
- #import "Person.h"
- @implementation Dog
- -(void)dealloc{
- //狗跑之前先把主人咬死
- [_p release];
- NSLog(@"The dog is gone....");
- [super dealloc];
- }
- @end
复制代码
【main.m文件】- #import <Foundation/Foundation.h>
- #import "Person.h"
- #import "Dog.h"
-
- int main(int argc, const char * argv[])
- {
-
- @autoreleasepool {
- //实例化一个person对象
- Person *p = [Person new]; //p的计数器值 1
- Dog *dog = [Dog new];//dog的计数器值 1
-
- p.dog = dog;//dog的计数器值 2
-
- dog.p = p;//p的计数器值 2
-
- [dog release];//dog的计数器值 1
- [p release];//p的计数器值 1
- }
-
- return 0;
- }
复制代码
【结果分析】最后dog和p的计数器值都为1.最后两个对象的堆区内存都没有被释放,导致了内存泄露。 【误区】 一开始我认为在delloc方法中,两个对象不都把拥有的对象给release掉了么?怎么也想不明白为什么最后计数器值都为1。最后终于明白了,只要记住一点【delloc只有在一个对象的计数器值为0的时候由系统自动调用的】就行了。这样是不是就明白了呢?
【解决方法1】任何一个对象多释放一次,不过这样需要注意顺序,具体需要计算他们的计数器值 - [dog release];//dog的计数器值 1
- [p release];//p的计数器值 1
- [p release];//p的计数器值 1
复制代码
【解决方法2:墙裂推荐】一端使用assign一端使用retain 只要把 Dog.h文件中的属性改为 - @property(nonatomic,assign) Person *p;
复制代码Dog.m文件中的方法改为 - -(void)dealloc{
- NSLog(@"The dog is gone....");
- [super dealloc];
- }
复制代码
此时打印结果: 2015-10-06 15:31:53.418 MRCDemo[1967:303] The god isgone.... 2015-10-06 15:31:53.420 MRCDemo[1967:303] This persondead....
|