在目标c中,一个类可以基本上删除自己吗?

时间:2012-06-01 20:15:40

标签: objective-c ios xcode

在目标c中,假设我有一个存储在NSMutableArray中的对象Obj,并且数组指向它的指针是整个程序中唯一指向Obj的强指针。现在假设我在Obj上调用了一个方法,并在另一个线程中运行此方法。在这种方法中,如果Obj将自身的指针设置为等于nil,它本质上会自行删除吗? (因为没有更强的指针了)我怀疑答案是否定的,但为什么呢?如果这确实有效,那么它是不好的编码实践(我认为它不是很好的编码,但它实际上是不好的?)

4 个答案:

答案 0 :(得分:5)

如果您的代码设计正确,则对象极不可能导致自己的释放/释放。所以,是的,你描述的情况表明编码实践不好,实际上可能导致程序崩溃。这是一个例子:

@interface Widget : NSObject
@property (retain) NSMutableArray *array;
@end

@implementation Widget

@synthesize array;

- (id)init
{
    self = [super init];
    if(self) {
        array = [[NSMutableArray alloc] init];
        [array addObject:self];
    }
    return self;
}

- (void)dealloc
{
    NSLog(@"Deallocating!");
    [array release];
    [super dealloc];
}

- (void)removeSelf
{
    NSLog(@"%d", [array count]);
    [array removeObject:self];
    NSLog(@"%d", [array count]);
}
@end

然后这段代码在另一个类中:

Widget *myWidget = [[Widget alloc] init];
[myWidget release];  // WHOOPS!
[myWidget removeSelf];

removeSelf中对NSLog的第二次调用将导致EXC_BAD_ACCESS,因为此时array已被解除分配,并且无法调用方法。

这里至少有几个错误。最终导致崩溃的一个事实是,无论什么类创建和使用myWidget对象,在它完成使用之前释放它(调用removeSelf)。没有这个错误,代码运行正常。但是,MyWidget不应该有一个实例变量,它首先会创建一个强引用,因为这会创建一个保留周期。如果有人试图在没有先调用myWidget的情况下释放removeSelf,则不会释放任何内容,并且您可能会发生内存泄漏。

答案 1 :(得分:0)

如果你的后向指针很弱(它应该是一个类,因为一个类永远不会尝试拥有它的所有者,你将最终得到一个保留周期)并从数组中删除强指针,该对象将被删除从堆。没有强烈的指针=从内存中移除。

您可以随时测试。

答案 2 :(得分:0)

如果你需要一个类来解决它被删除的情况,最好的做法是先保留/自动释放它然后让情况发生。在这种情况下,类不会在其方法的中间删除,而是仅在之后删除。

答案 3 :(得分:0)

我认为我们可以说可能是糟糕的编码习惯,具体取决于你的工作方式。有些方法可以安排,或者可能安全地进行。

所以我们假设我们有一个全局:

NSMutableArray *GlobalStore;

一种方法是将自己移除为最终行动:

- (void) someMethod
{
   ...
   [GlobalStore removeObject:self];
}

由于这是最后的行动,因此self将来不应该使用,而且一切都应该很好,可能......

其他选项包括使用0的时间延迟来安排删除 - 这意味着它将在下一次运行循环周围启动(当然,如果你有一个运行循环,那么它在一个线程中你可能没有)。这应该始终是安全的。

你也可以让一个对象保持对自身的引用,这会产生一个循环,因此会保持它的存活。当它准备好死时,如果没有其他引用并且这是最后一个动作(或者是另一个对象的预定动作),它就可以自己引用它,那么该对象就已经死了。