Objective-C:从自身释放对象

时间:2011-07-08 14:10:42

标签: objective-c

我偶然发现一个有趣的情况,当物体可以自我释放,并且想知道在这种情况下什么是安全的。

想象一下,我们有一个Foo类:

@implementation Foo
+ (Foo *) foo {
    return [[[Foo alloc] init] autorelease];
}

- (void)resign {
    [FooHolder holder].foo = nil;

    // here's where the things happen
}
@end

另一个类是FooHolder(具有一个属性的单例):

@interface FooHolder : NSObject {
    Foo *foo;
}

@property (retain) Foo *foo;

+ (FooHolder *)holder;

@end

在代码的某处我们执行此操作(先调用stepOne然后调用stepTwo;在stepOne完成后自动释放池耗尽:

- (void)stepOne {
    Foo *foo = [Foo foo];

    [FooHolder holder].foo = foo;
}

- (void)stepTwo {
    [[FooHolder holder].foo resign]
}

如果我尝试在self方法中访问resign,在分配后,使用NSZombieEnabled,我收到一条警告,self已被解除分配。这给了我短暂的WTF时刻,但好吧,我可以在这部分没有访问self的情况下生活。令我困扰的是,如果对象已经被释放,谁可以保证堆栈没有被损坏,我们正在使用我们的本地和实例变量正常进行?一般来说,在方法中允许self被释放是不好的做法吗?

2 个答案:

答案 0 :(得分:5)

  

一般来说,在方法中允许自我释放是不好的做法吗?

是的,因为从自我解除分配的角度来看,你的所有伊娃都可以被解除分配。

我不会假装了解您的设计或理由,但为什么不重新安排辞职方法:

- (void)resign {
    // here's where the things should happen
    [FooHolder holder].foo = nil;
}

您应该在有可能使用它们之后释放所拥有的对象,就像您在[super dealloc]; end 调用-(void)dealloc一样

答案 1 :(得分:3)

我认为你的设计有缺陷。在实例方法-resign中,您实际上释放了由单例持有的foo的特定实例。为什么foo的任意实例会这样做?在实例方法中引用有效的全局变量会使耦合过于紧张。

无论调用-resign是什么,都应告诉[FooHolder holder]它已经辞职foo或将辞职foo。或者,对FooHolder中的foo进行弱引用,并让foo向其发送-willResign:(Foo*)之类的消息。这有效地使其成为foo的代表}。在-willResign:中,FooHolder可以检查它是否是正确的foo,然后在将其设置为nil之前保留并自动释放它。