假设场景与说明:
1、Person对象有个成员变量为Card对象,Card对象中有个成员变量为Person对象;
2、Person对象将Card对象做为其成员变量,需要引入头文件"Card.h",同样Card对象将Person对象做为其成员变量,需要引入头文件"Person.h",那么两个头文件相互引用,会千万死循环,OC中通过使用#import替代C语言中的#include解决了多次引用的问题,但解决不了循环引用的问题,所以在这种情况下,通过@class Person或者@class Card来解决声明问题,至少要有一方使用该方法声明类,才能解决循环引用的问题;
3、另外一个问题:相互retain,要常规模式下,一个对象做为另一个对象的成员变量,示意图如下所示:
4、Card对象做为Person对象的成员变量,创建并赋值给_card后,当前有两个拥有者,所以retainCount = 2,进行[c release]操作后,只有_card对其拥有所有权,如果Person对象执行release操作,同时会在dealloc方法中对_card进行release操作,这样对象成功释放,符合黄金法则,一切正常。
5、但如果Card对象中同时也有一个_person对象对Person对象c也有拥有权,这样一来两个对象都无法被释放,先看示意图,再说明不能释放的关键点:
6、如果以Person为主,Card * c做为其成员对象,原则上创建好对象赋值给_card后,将临时变量c进行释放,但c同时又是另一个对象的主对象,因而Card * c在进行alloc操作分配存储空间后只会做一次release操作,不可能做两次release,可事实上,c在赋值给Person * p的成员变量_card时进行了一次retain操作,此时retainCount = 2;
7、如果以Card为主,面临同样的问题,所在关键点在于,两个对象的retainCount值由于相互赋值时都增加了1,进行一次release后,不会调用dealloc方法,所以第二次release无法触发,从而两对象处于互等状态;
8、解决这个问题的办法:将其中一个对象在声明时@property (nonatomic, retain) 时,将retain改成assign,只修改其中一个即可,问题得以解决;
参考代码:
Person.h- //
- // Person.h
- // Retain-1
- //
- // Created by yusian on 14-3-19.
- // Copyright (c) 2014年 小龙虾论坛. All rights reserved.
- //
- #import <Foundation/Foundation.h>
- @class Card;
- @interface Person : NSObject
- @property (nonatomic, retain) Card *card;
- @end
复制代码
Person.m- //
- // Person.m
- // Retain-1
- //
- // Created by yusian on 14-3-19.
- // Copyright (c) 2014年 小龙虾论坛. All rights reserved.
- //
- #import "Person.h"
- @implementation Person
- - (void)dealloc
- {
- NSLog(@"Person is dealloc...");
-
- [_card release];
-
- [super dealloc];
- }
- @end
复制代码 Card.h- //
- // Card.h
- // Retain-1
- //
- // Created by yusian on 14-3-19.
- // Copyright (c) 2014年 小龙虾论坛. All rights reserved.
- //
- #import <Foundation/Foundation.h>
- @class Person;
- @interface Card : NSObject
- @property (nonatomic, assign) Person * person;
- @end
复制代码 Card.m- //
- // Card.m
- // Retain-1
- //
- // Created by yusian on 14-3-19.
- // Copyright (c) 2014年 小龙虾论坛. All rights reserved.
- //
- #import "Card.h"
- @implementation Card
- - (void)dealloc
- {
- NSLog(@"Card is dealloc...");
-
- //[_person release];
-
- [super dealloc];
- }
- @end
复制代码 main.m- //
- // main.m
- // Retain-1
- //
- // Created by yusian on 14-3-19.
- // Copyright (c) 2014年 小龙虾论坛. All rights reserved.
- //
- #import <Foundation/Foundation.h>
- #import "Person.h"
- #import "Card.h"
- int main()
- {
- Person * p = [[Person alloc] init];
-
- Card * c = [[Card alloc] init];
-
- p.card = c;
-
- c.person = p;
-
- [p release];
- [c release];
- return 0;
- }
复制代码 运行结果:
2014-03-19 16:27:33.036 Retain-1[1709:303] Person is dealloc... 2014-03-19 16:27:33.037 Retain-1[1709:303] Card is dealloc... Program ended with exit code: 0
|