繁体   English   中英

在目标C的dealloc中使用setter?

[英]Use of setter in dealloc in Objective C?

以下代码有问题吗?

- (void) dealloc {
    self.foo = nil;
}

代替

- (void) dealloc {
   [_foo release];
   _foo = nil;
}

不采用前者有两个原因:

  1. 如果子类已覆盖设置程序,则释放可能实际上不会发生。

  2. 使用设置器可能会触发KVO通知,并且观察者将从技术上不存在的对象收到通知。

另一方面,如果使用ARC,则无需执行任何操作。

不建议这样做的原因是它可能会引起问题。 setter或getter可能有副作用

以内存泄漏为例。

- (void)dealloc;
{
    self.iWillLeak = nil;
    self.iCauseTheLeak = nil;
    [super dealloc];
}

- (void)setICauseTheLeak:(NSArray *)iCauseTheLeak;
{
    if (_iCauseTheLeak != iCauseTheLeak) {
        [_iCauseTheLeak release];
        _iCauseTheLeak = [iCauseTheLeak retain];
    }
    self.iWillLeak = [NSArray array]; // This was already cleared in dealloc
}

这是一个简单的案例,并且有可能发生更具破坏性的事情。

这里的主要结论是,两者在做不同的事情时并不等同。

如果您使用retaincopy属性声明了foo属性,则没有问题,但是如果使用assign ,则不应该执行[_foo release];

您可能会发现以下阅读很有用: 惰性的Objective-C内存管理

我将写两个例子:

1 /直接使用发布


- (void)dealloc {
    [foo_ release];
    [super dealloc];
}

- (void)setFoo:(Foo*)foo {
   if (foo == foo_) {
       return;
   }

   [foo_ removeObserver:self];
   [foo_ release];

   foo_ = [foo retain];
   [foo_ addObserver:self];
}

foo_的观察者将不会被删除,这可能是一个错误。

2 /使用二传手


- (void)dealloc {
    self.observer = nil;
    self.foo = nil;
    [super dealloc];
}

- (void)setFoo:(Foo*)foo {
   if (foo == foo_) {
       return;
   }

   [foo_ removeObserver:self.observer];
   [foo_ release];

   foo_ = [foo retain];
   [foo_ addObserver:self.observer];
}

如您所见,这里出现另一个错误。 我们在可能不会出现nil某个地方使用nilself.observer )。

通常,这两种情况都不会帮助您捕获错误。 在每种情况下,都会出现不同类型的越野车行为。

我的建议是使用二传手保持一致性,但这是一个见解。 无论如何,如果您编写自己的setter,请检查是否按正确的顺序初始化和取消分配属性。 还要注意,您的设置器可以在子类中被覆盖。

Apple建议直接在init和dealloc中使用保留/释放,但是在自己的代码中,他们使用setter(例如, UITableView在分配时使用nil参数调用setDelegate )。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM