将自释放对象转换为ARC

arc*_*tle 10 macos cocoa design-patterns memory-management automatic-ref-counting

好的,Apple给我们带来了ARC,这很棒.在将我的应用程序重构为AR​​C之后,几乎所有工作都正常,现在开发和维护起来要容易得多.

只有一个问题我仍然无法弄清楚.

我的工作管理程序在自己的窗口中显示提案,订单等的不同详细信息.所以我有一个特殊的类,其中WindowControllers被分配并使用initWithWindowNibName启动,然后窗口显示为showWindow:

DetailWindowController *proposalWindowController = [[DetailWindowController alloc] initWithWindowNibName:@"ThePorposalWindow"];
[proposalWindowController showWindow:nil];
Run Code Online (Sandbox Code Playgroud)

在ARC之前,WindowController的实例执行了如文档中所示的发布:

- (void)windowWillClose:(NSNotification *)notification
{
   [self autorelease];
}
Run Code Online (Sandbox Code Playgroud)

但是现在使用ARC这是不可能的,更糟糕​​的是,在我分配和启动WindowController的特殊类中,ARC释放了相同的windowController,因为没有指向windowController的指针.

我的想法是将windowController复制到一个可变数组中:

[proposalWindowArray addObject:proposalWindowController];
[[proposalWindowArray lastObject] showWindow:nil];
Run Code Online (Sandbox Code Playgroud)

并在windowControllers委托方法windowWillClose中我向我的特殊类发布通知:

- (void)windowWillClose:(NSNotification *)notification
{
    [[NSNotificationCenter defaultCenter] postNotificationName:@"ProposalWindowWillClose" object:[[self window] windowController] userInfo:nil];
}
Run Code Online (Sandbox Code Playgroud)

在我的特殊类中,我听取通知并从数组中删除对象:

- (void) proposalWindowWasClosed: (NSNotification *) notification
{
    [proposalWindowArray removeObjectIdenticalTo:[notification object]];
}
Run Code Online (Sandbox Code Playgroud)

它有效,但我仍然不相信这是正确的方法.

有没有人有同样的问题或提示让它变得更好?

Rob*_*ier 10

我可能会使用委托方法而不是通知.通常,最好有一个跟踪打开窗口的外部对象.像你的旧系统一样,自我保留的对象打破了对象所有权的基本点,使得很难找到东西(例如"给我一个打开的窗口列表").那些只是"漂浮"在那里的非单身人士经常会回来在你的建筑中咬你(我必须经常解决这个问题).

也就是说,有时自我所有权至少是方便的,最糟糕的是不是世界末日.所以自己拥有.唯一的区别是你需要明确地做,而不是匹配泄漏和过度释放(这是你的旧代码正在做的).

创建一个私有strong财产.分配self给它.这将创建一个保留循环,在您将属性设置为之前一直保持这种循环nil.

  • 根据系统的不同,我经常只有一个中央的`WindowManager`单例,让它看一下`NSWindowWillCloseNotification`,但有时我会按照你的说法使用委托.取决于它需要的集成程度.WindowManager通常拥有系统中的所有WindowControllers.这就是我经常发现的设计,当我完成时,我就结束了. (3认同)