很多人似乎都在使用像
这样的宏#define SAFE_RELEASE(X) [X release]; X = nil;
(包括我自己)。
我一直在重新评估我为什么要使用它,并希望画出一些意见。
使用这个宏的目的(我认为)是这样的,如果你在发布它之后意外地使用你的对象,那么你将不会得到一个糟糕的访问异常,因为objective-c会相当当对象为零时,请高兴地忽略它。
我觉得这有可能掩盖一些不起眼的错误。当你再次尝试使用X时,程序实际上可能会崩溃。在测试期间,您可以找到问题并改进代码。
这个宏是否鼓励懒惰编程?
思想?
答案 0 :(得分:6)
我认为你在讨论你的问题中的所有优点和缺点,所以我没有大量的补充。我个人不使用该构造。正如您所建议的那样,可以用于记录人们无法正确理解内存管理的区域。我的偏好是修复bug而不是症状。
然而,我不时看到的一个妥协是:
var = nil;
这样,可能对付费客户更可靠,并且在开发过程中仍然会早期崩溃。
我也不是很喜欢这个,因为你正在为你的用户使用不同的代码,只是因为错误的版本一直在运行并不意味着它正在做正确的事情。没有崩溃但是破坏你的数据库不是理想的行为......
答案 1 :(得分:2)
我认为,或者像self.myVar = nil这样的等价物,如果适用的话,是好的。在许多情况下,您根本无法分配nil并假设任何后续访问都是错误。
例如在UIKit中,当操作系统询问时,释放尽可能多的资源是一种很好的行为。 E.g。
- (void)didReceiveMemoryWarning
{
[myCachedData release];
[super didReceiveMemoryWarning];
}
现在,当我下次使用我的课时,我怎么知道myCachedData现在无效?唯一的方法(没有ANOTHER变量作为标志)是在释放后将myCachedData设置为nil。将这两条繁琐的线条合并为一条正是SAFE_RELEASE的用途。
答案 2 :(得分:1)
你没有需要它,但它很方便。我在我的应用中使用类似的东西。你可以认为它是“懒惰的”,但当你有大约20个对象时,手动编写这些对象变得乏味。
答案 3 :(得分:1)
我正在研究同样的问题。随着阅读的一点点,我做了类似的事情:
#define DEBUGGING
//#define PRODUCTION
#ifdef DEBUGGING
#define SAFE_RELEASE(X) [X release];
#else
#define SAFE_RELEASE(X) [X release]; X = nil;
#endif
因此,如果我正在开发,我会得到崩溃。在生产中我没有。
斯科特< -
答案 4 :(得分:1)
正如安德鲁所指出的那样,在某些情况下,分配nil
不仅可以避免错误,而且是必要的。只需考虑典型的UIViewController
代码
- (void)viewDidLoad {
button = [UIButton buttonWithType:UIButtonTypeRoundedRect]; // autoreleased
[button retain]; // keep alive
}
- (void)viewDidUnload { // view has been removed
[button release];
}
- (void)dealloc { // destroying the view controller
[button release]; // <-- problem
}
如果加载控制器,稍后卸载(因为显示另一个视图控制器,内存运行不足)并最终销毁,[button release]
中的dealloc
将过度释放按钮(发送一个消息发布的对象)。因此,有必要指定nil。安全的解决方案是:
- (void)viewDidUnload { // view has been removed
[button release];
button = nil;
}
- (void)dealloc { // destroying the view controller
[button release]; // <-- safe
}
对于那些情况,宏很好用。为了更明确地说明它的作用,最好将其命名为RELEASE_AND_NIL
#define RELEASE_AND_NIL(X) [X release]; X = nil;