Person.h
#import
@interface Person : NSObject {
NSString *name;
int age;
Person *spouse;
}
@property (nonatomic, retain) NSString* name;
@property int age;
@property (nonatomic, retain) Person *spouse;
- (id) initWithName:(NSString *)n age:(int)a;
- (id) initWithName:(NSString *)n age:(int)a spouse:(Person*)s;
@end
Person.m
@implementation Person
@synthesize name;
@synthesize age;
@synthesize spouse;
-(id) initWithName:(NSString *)n age:(int)a
{
return [self initWithName:n age:a spouse:nil];
}
-(id) initWithName:(NSString *)n age:(int)a spouse:(Person *)s
{
if((self = [super init]))
{
self.name = n;
self.age = a;
self.spouse = s;
}
return self;
}
-(NSString *)description
{
return [NSString stringWithFormat:@"name=%@, age=%d, spouse=%@", self.name, self.age, self.spouse.name];
}
- (void) dealloc
{
[name release];
[spouse release];
[super dealloc];
}
@end
Then I have code like this
Person *person1 = [[Person alloc] initWithName:@"Matt" age:33];
Person *person2 = [[Person alloc] initWithName:@"Clair" age:29 spouse:person1];
person1.spouse = person2;
NSLog(@"%@", person1);
NSLog(@"%@", person2);
NSLog(@"person1.retainCount=%d, person2.retainCount=%d", person1.retainCount, person2.retainCount);
[person2 release];
NSLog(@"person1.retainCount=%d, person2.retainCount=%d", person1.retainCount, person2.retainCount);
[person1 release];
NSLog(@"person1.retainCount=%d, person2.retainCount=%d", person1.retainCount, person2.retainCount);
At last, person1.retainCount=1 person2.retainCount=1, they never get -(void) dealloc, so when this situation comes up, how to deal with…
What you have here is called a retain cycle and it is the biggest flaw with a reference counting memory management scheme. This is why the convention that delegates are not retained exists.
You need to find a way to either break the cycle (e.g. before releasing a person, set their spouse to nil, and possibly their spouse’s spouse) or avoid it altogether. You could, for instance, create a marriage class with two
assignproperties, one for each partner, and instead of a spouse property, each person has aretainmarriage property pointing to the marriage object. Then when a person is deallocated (and it will be now), you set the marriage property for the other partner to nil.So your interfaces will look something like this:
Person’s dealloc would look something like this.
Person’s partner property is implemented thus:
You could also do it the other way around so that the marriage owns the people and the people have a weak reference to the marriage.