retain的循环引用注意以及@class的使用

来源:互联网 发布:mac如何ping ip地址 编辑:程序博客网 时间:2024/05/17 06:16

对于retain有一种是循环引用,所谓的循环引用就是两个对象中,互相包含对方,当你在调用我的时候retain一次,而我也调用你的时候也retain一次,导致谁也不能被回收。解决方式就是两对象中的实例变量(oc对象类型)在写@property参数时:

一个写为@propertynonatomic,retainPerson *Person

一个写为@property nonatomic,assignCar *Car

 

下面找个写代码来说明实质性的问题:

有两个类PersonCard,一个人拥有一辆车,一辆车对应一个人。所以代码如下:

1)Person.h #import <Foundation/Foundation.h>@class Car;@interface Person : NSObject@property (nonatomic,retain) Car *car;@end2)person.m#import "Person.h"#import "Car.h"@implementation Person-(void)dealloc{    [_car release];    NSLog(@"Person对象被回收");    [super dealloc];}@end3)Car.h#import <Foundation/Foundation.h>@class Person;@interface Car: NSObject@property (nonatomic,assign)Person *person;@end4)Car.m#import "Car.h"@implementation Car-(void)dealloc{    NSLog(@"car对象被回收");    [super dealloc];}@end5)main.#import <Foundation/Foundation.h>#import "Car.h"#import "Person.h"int main(int argc, const char * argv[]) {        //p-1(计数器是1)    Person *p = [[Person alloc]init];    //c-1    Car *c = [[Car alloc] init];    //c-2    p.car = c ;    //p-1    c.person = p;    //c-1    [c release];    //p-0,c-0    [p release]    return 0;}

图分析如下:

如果两个类中都写为@property(nonatomic,retain)Person *p;

@property(nonatomic,retain)Car *c;

 

程序执行过程中 内存如图所示:



程序结束后,对象并没有被回收,所以造成内存泄露。




如果Car.h中把@property参数中的retain改为assign,则意味着只是赋值,_person不用执行retain操作,所以当执行到[p release]时 p的计数器从1-0,所以对象p回收,进入到p的dealloc方法中,执行[_car release],c的计数器从1-0;回收对象c,然后回收对象p;

所以循环引用解决方式:

一端用retain

一端用assign

 

值得注意的是: @class 类A 一般用于类B.h 文件  表示在类B中声明有一个类A,当然仅仅是声明,并不是把类A的属性和方法拷贝过来。而#import  则是把属性和方法全拷贝过来,如果很多文件都#imoport这个文件的话,当这个头文件被修改时,则那些很多的文件都需要重新编译,但是@class则不需要,它只需要在用到时,在类B.m文件中#import既可。


0 1