0

我有一个对象被设置为另一个对象的委托,该对象的delegate属性很弱。

- (YYService *)service
{
  XXHandler *handler = [[XXHandler alloc] init];

  // YYService's "delegate" property is weak
  return [[YYService alloc] initWithDelegate:handler];

  // The XXHandler is deallocated because there are no strong references to it
}

由于没有其他东西引用该委托,因此它最终会被释放,但我希望它能够持续存在,只要父对象就像父对象对其委托有强引用一样。有没有一种简单的方法可以做到这一点?

4

1 回答 1

0

“解决”这个问题的简单原因是子类YYService化,给子类一个额外的强属性并将其设置在-initWithDelegate:.

但是这个“解决方案”会加深你设计中的一个问题,而不是解决这个问题。

让我们看看,为什么代表通常被弱持有:

委派类有一个可能不适合该类用户的情况的一般(或没有)行为,即如果发生某些事情。(操作完成,发生错误,$whatever)因此委托类为您提供了自定义行为的机会,包括运行自定义代码。委托与子类化竞争,但与子类化的区别在于每个实例(而不是每个类)和运行时(而不是编译时)。

因为它在每个实例的基础上工作,所以创建委托的实例通常会强烈地持有委托实例。此代码知道应该应用于委托实例的自定义:

-(void)createDelegate
{
  self.delegating = [Delegating new]; // I create and hold the instance strongly
  delegating.delegate = self;         // I customize it
}

然后委托实例不能强持有委托,因为这将是一个保留循环。

在您的代码段中不起作用,因为-service返回新创建的委托实例。即使可以返回两个实例,我也不喜欢它,因为创建委托对象和安装委托将是一个两步操作,即使它在语义上是一步操作。所以如果你没有self作为委托人,你应该用一种方法完成整个安装过程:

-(void)installService
{
  self.handler = [[XXHandler alloc] init]; // Hold the handler strongly
  self.service = [[YYService alloc] initWithDelegate:handler];
}

如果您不知道充当委托的具体实例对象,请将其作为参数传递:

-(void)installServiceWithDelegate:(id)delegate
{
  self.delegate = delegate;
  self.service = [[YYService alloc] initWithDelegate:delegate];
}

…

[self installServiceWithDelegate:[YourConcreteClass new]];

但是你不应该试图把事情颠倒过来或翻过来

于 2015-08-19T04:14:48.923 回答