1

我是 cocoa 的新手,因为我正在编写 cocoa 应用程序,所以我总是很困惑如何释放一个告诉它的委托我已经完成的对象。听者试图释放它。

所以我有一个 AppController,它提供一个 updateCheckWindowController 并充当它的代表,以便当 updateCheckWindow 结束时它可以采取进一步的行动(在我的情况下释放它)。UpdateCheckWindowController 在窗口结束时调用委托,因此该调用转到 AppController 的方法,该方法试图释放调用对象 updateCheckWindowController。

由于 AppController 是唯一保留它的人,因此调用发布应该会破坏 updateCheckWindowController ,但 updateCheckWindowController 对象当前位于 callStack 上,因为它是 AppController 上的一个调用委托方法,并且 AppController 试图释放它。它的一种循环调用

它在objective-c中是如何工作的?这看起来像一个非常糟糕的模式,不像有一个公平的理由。还是我的做法不正确?

4

3 回答 3

1

您的判断可能是正确的,可以使用更好的模式来完全避免循环调用。

如果你有一个视图控制器在短时间内呈现,然后在关闭时应该被释放,你可以使用 UIViewController 的这个方法:

presentViewController:动画:完成:

您可以在呈现之前自动释放正在呈现的视图控制器。调用此方法将保留它。当控制器应该被解除时,它可以告诉它的委托,委托可以调用

解雇视图控制器:动画:完成。

当代表解雇它时,它将被释放。

是这种情况还是更复杂?

于 2013-07-13T14:57:07.127 回答
0

调用堆栈在这里不会造成任何问题。只要 UpdateCheckWindowController 在调用后它被释放后不做任何事情,你会没事的。

有关如何更好地组织控制器生命周期的信息,请参阅 bbrame 的答案。我将只解释原始架构的内存管理后果。

所以,如果我的情况是正确的,你就会有以下类似的情况。someMethod如果您在self委托方法调用之后没有以任何方式引用,即使在返回之前可能会释放对象,它也会正常工作。

请注意,当委托方法返回时,UIKit 可能仍会引用您的视图控制器。也就是说,如果该视图控制器仍然是导航堆栈的一部分。在这种情况下,您不必担心它被过早释放,它只会在您的方法返回并且控件返回运行循环后才会发生。

@interface AppController: NSObject

@property (nonatomic, strong) UpdateCheckWindowController *ctrl;

- (void)updateCheckWindowController;
- (void)iAmDoneReleaseMe;

@end

@implementation AppController

- (void)updateCheckWindowController {
    UpdateCheckWindowController *ctrl = [[UpdateCheckWindowController alloc] initWithDelegate:self];
    // ...

    // Retain the controller
    self.ctrl = ctrl;
}

- (void)iAmDoneReleaseMe {
    self.ctrl = nil;
}

@end


@interface UpdateCheckWindowController: NSObject

// Make it weak so we don't have a retain cycle
@property (nonatomic, weak) AppController *delegate;

@end

@implementation UpdateCheckWindowController

- (void)someMethod
{
    // do all the finishing work here
    // ...

    // now call the delegate that will release us
    [self.delegate iAmDoneReleaseMe];

    // don't do anything else here and you'll be fine
}

@end
于 2013-07-13T14:59:10.597 回答
0

这可能就像使用自动释放而不是释放一样简单。Autorelease 通常在调用堆栈展开之前不会执行实际的释放。

于 2013-07-13T15:27:56.763 回答