Objective-C属性无限循环

时间:2014-11-14 03:15:21

标签: ios objective-c

我目前正在学习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,它再次调用自己),但我无法找到一个优雅的解决方案来解决这个问题。

任何帮助 - 解释它是如何工作的 - 将不胜感激!

非常感谢!

3 个答案:

答案 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,方法什么都不做。