Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Objective-C property infinite loop

I'm currently learning Objective-C and it's also my first foray into programming so please bear with me.

I have a simple object called XYZPerson that holds a person's first name, last name and a reference to his or her partner. The partner also being an XYZPerson object.

Here's what I declared in the XYZPerson's header :

@interface XYZPerson : NSObject

@property (nonatomic, copy) NSString *firstName;
@property (nonatomic, copy) NSString *lastName;
@property (nonatomic, weak) XYZPerson *partner;

@end

and in the implementation I wrote this:

- (void)setPartner:(XYZPerson *)aPartner
{
    _partner = aPartner;
    aPartner.partner = self;
}

but in main(), whenever I call personMale.partner = personFemale; it creates an infinite loop.

I think I understand why (because aPartner.partner calls setPartner which calls itself and again), but I can't find an elegant solution to correct this problem.

Any help — with explanations of how it works — would be much appreciated!

Thanks a lot!

like image 502
Antony Kwok Avatar asked May 18 '26 04:05

Antony Kwok


1 Answers

The problem is that this line:

aPartner.partner = self;

does something you didn't realize it would do: it is merely a shorthand for calling setPartner:. Setting a property calls the corresponding setter method; that in fact is all a property really is, i.e. a way of calling a setter/getter method!

But that line is in the implementation of setPartner:. So you are now in an infinite recursion: you are calling yourself. It is exactly as if you said:

- (void)setPartner:(XYZPerson *)aPartner
{
    _partner = aPartner;
    [aPartner setPartner: self];
}

which, since these are all XYZPersons, is obviously a recursion.

After all, you would never say this:

- (void)setPartner:(XYZPerson *)aPartner
{
    [self setPartner: = aPartner];
}

But that in fact is just the kind of thing you are saying!

When you are in a setter, for this very reason, you must never call the setter; you should refer only to the underlying instance variable:

- (void)setPartner:(XYZPerson *)aPartner
{
    self->_partner = aPartner;
    aPartner->_partner = self;
}
like image 63
matt Avatar answered May 20 '26 21:05

matt



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!