我只能解决一个问题。
我的工作管理程序在自己的窗口中显示提案,订单等的不同详细信息。所以我有一个特殊的类,其中WindowControllers被分配并使用initWithWindowNibName启动,然后窗口显示为showWindow:
DetailWindowController *proposalWindowController = [[DetailWindowController alloc] initWithWindowNibName:@"ThePorposalWindow"];
[proposalWindowController showWindow:nil];
在ARC之前,WindowController的实例执行了documentation中所示的发布:
- (void)windowWillClose:(NSNotification *)notification
{
[self autorelease];
}
但是现在使用ARC这是不可能的,更糟糕的是,在我分配和启动WindowController的特殊类中,ARC释放了相同的windowController,因为没有指向windowController的指针。
我的想法是将windowController复制到一个可变数组中:
[proposalWindowArray addObject:proposalWindowController];
[[proposalWindowArray lastObject] showWindow:nil];
在windowControllers委托方法windowWillClose中我将通知发布到我的特殊类:
- (void)windowWillClose:(NSNotification *)notification
{
[[NSNotificationCenter defaultCenter] postNotificationName:@"ProposalWindowWillClose" object:[[self window] windowController] userInfo:nil];
}
在我的特殊课程中,我听取通知并从数组中删除对象:
- (void) proposalWindowWasClosed: (NSNotification *) notification
{
[proposalWindowArray removeObjectIdenticalTo:[notification object]];
}
它有效,但我仍然不相信这是正确的方法。
是否有人有同样的问题或提示让它变得更好?
答案 0 :(得分:10)
我可能会使用委托方法而不是通知。通常,最好有一个跟踪打开窗口的外部对象。像你的旧系统一样,自我保留的对象打破了对象所有权的基本点,使得很难找到东西(例如“给我一个打开的窗口列表”)。只是“漂浮”在那里的非单身人士经常会回来在你的建筑中咬你(我必须经常解决这个问题)。
尽管如此,有时自我所有权至少是方便的,最糟糕的是不是世界末日。所以自己拥有。唯一的区别是你需要明确地做,而不是匹配泄漏和过度释放(这是你的旧代码正在做的事情)。
创建私有strong
属性。为其分配self
。这将创建一个保留循环,在您将属性设置为nil
之前将其保持不变。
答案 1 :(得分:0)
没有黑客,除了在其他对象中强烈引用对象之外,没有优雅的方法来保留对象。例如,您可以保留静态NSMutableArray
/ NSMutableSet
,在那里添加控制器,然后在windowsWillClose:
中将其删除。这比发布通知要短。为了使这个可重用,请创建一个带有数组的WindowControllerRegistry
单例,在这里添加像这样的控制器,它将自动侦听NSWindowWillCloseNotification
并将其从数组中删除,从而释放所有权。
作为一种快速解决方法,您可以non-ARC file执行retain
/ autorelease
次来电:
my_retain(self);
my_autorelease(self);
// ArcDisabled.mm
void my_retain(id obj) { [obj retain]; }
void my_autorelease(id obj) { [obj autorelease]; }
答案 2 :(得分:0)
我认为您的替代方法应该是正确的,但我认为您不需要第二次通知。你应该能够做到:
- (void)windowWillClose:(NSNotification *)notification
{
[proposalWindowArray removeObjectIdenticalTo:self];
}
假设“proposalWindowArray”是静态NSMutableArray。
答案 3 :(得分:0)
当我切换到ARC时,我遇到了同样的问题。您的解决方案有效,但您将其变得过于复杂。你可以基本上做你以前做过的事情,让窗户在关闭时释放,但是以ARC兼容的方式。
解决方案是在类本身内简单地创建类的属性。对于您的示例,在DetailWindowController中,您将添加以下属性:
@property (strong) DetailWindowController *theWindowController;
然后,当您使用上面的代码创建窗口时,添加一行,如下所示:
DetailWindowController *proposalWindowController = [[DetailWindowController alloc] initWithWindowNibName:@"ThePorposalWindow"];
[preferenceController setTheWindowController:proposalWindowController];
[proposalWindowController showWindow:nil];
最后,让ARC在关闭时释放窗口,就像在自动释放前使用ARC一样,在DetailWindowController类中,只需执行:
- (void)windowWillClose:(NSNotification *)notification
{
// Let ARC tear this down and clean it up
[self setTheWindowController:nil];
}