我目前正在学习Objective-C,这也是我第一次尝试编程,所以请耐心等待。
我有一个名为XYZPerson的简单对象,它包含一个人的名字,姓氏和对他或她的伴侣的引用。合作伙伴也是XYZPerson对象。
这是我在XYZPerson的标题中声明的内容:
@interface XYZPerson : NSObject
@property (nonatomic, copy) NSString *firstName;
@property (nonatomic, copy) NSString *lastName;
@property (nonatomic, weak) XYZPerson *partner;
@end
在实施中我写了这个:
- (void)setPartner:(XYZPerson *)aPartner
{
_partner = aPartner;
aPartner.partner = self;
}
但是在main()中,每当我调用personMale.partner = personFemale;
时,它都会创建一个无限循环。
我想我理解为什么(因为aPartner.partner调用setPartner,它再次调用自己),但我无法找到一个优雅的解决方案来解决这个问题。
任何帮助 - 解释它是如何工作的 - 将不胜感激!
非常感谢!
答案 0 :(得分:5)
问题是这一行:
aPartner.partner = self;
做了一些你没有意识到它会做的事情:它只是一个调用setPartner:
的简写。设置属性会调用相应的setter方法;事实上,这实际上是一个属性,即一种调用setter / getter方法的方法!
但该行是 in setPartner:
的实现。所以你现在正在进行无限递归:你在称自己为自己。它就像完全,就像你说的那样:
- (void)setPartner:(XYZPerson *)aPartner
{
_partner = aPartner;
[aPartner setPartner: self];
}
,因为这些都是XYZPersons,显然是一个递归。
毕竟,你永远不会这样说:
- (void)setPartner:(XYZPerson *)aPartner
{
[self setPartner: = aPartner];
}
但实际上这只是你 所说的那种东西!
当你在一个制定者中时,出于这个原因,你绝不能打电话设定者;你应该只引用底层的实例变量:
- (void)setPartner:(XYZPerson *)aPartner
{
self->_partner = aPartner;
aPartner->_partner = self;
}
答案 1 :(得分:1)
在您的设置器中,只有在合作伙伴正在更改时才进行分配:
- (void)setPartner:(XYZPerson *)aPartner
{
if(_partner != aPartner) {
_partner = aPartner;
aPartner.partner = self;
}
}
另一个解决方案是创建一个单独的方法来建立两个人合作伙伴。
- (void)makePartner:(XYZPerson *)aPartner {
self.partner = aPartner;
aPartner.partner = self;
}
答案 2 :(得分:1)
想想在XYZPerson上调用setPartner时会发生什么。
让我们说你说
XYZPerson *a = [[XYZPerson alloc] init];
XYZPerson *b = [[XYZPerson alloc] init];
a.partner=b;
在a person的setPartner方法中,它将其合作伙伴属性设置为其他人(b),然后调用person b的setPartner方法..
好的,现在人b的setPartner方法会触发。在该方法中,它设置了自己的伙伴属性,然后告诉它的新伙伴(人a)将其伙伴属性设置为自己(人b),再次调用人的setPartner方法,依此类推,无限制。 (永远)
您可以使用if语句打破循环:
- (void)setPartner:(XYZPerson *)aPartner
{
if (_partner != aPartner)
{
_partner = aPartner;
aPartner.partner = self;
}
}
现在,使用修改后的代码,序列将是:
a.partner = b;
person的合作伙伴属性为nil,因此将其设置为b,然后调用b的setPartner方法。
在人b的setPartner方法中,它的伙伴也是零,所以人b将它的伙伴属性设置为人a,然后再次调用人的a的setPartner方法。
但是,这次人的伙伴属性已经指向人b,所以if语句的计算结果为false,方法什么都不做。