管理类方法中创建的实例的生命周期的更好方法

时间:2011-07-22 19:07:25

标签: objective-c cocoa cocoa-sheet

在我正在写的宠物应用程序中,在主窗口上,我有一些彼此对齐的自定义视图,每个视图都有一个标签,一个组合框和一个按钮。

单击该按钮会调用在同一视图中找到组合框的代码,然后调用以下函数(RVListEditorController的类方法):

+ (void) editComboBox: (NSComboBox *) aComboBox
{
    // Analyze says "possible leak", but both methods ending the panel will release the controller.

    RVListEditorController *controller = [[RVListEditorController alloc] initWithComboBox: aComboBox];

    [NSApp beginSheet: [controller window]
       modalForWindow: [aComboBox window]
        modalDelegate: controller
       didEndSelector: NULL
          contextInfo: nil];
}

代码创建RVListEditorController的实例。它控制一个面板,允许我编辑组合框中的列表(删除项目,排序项目等)。除了其他控件之外,它还有两个关闭它的按钮,取消和OK。

两个按钮的代码是:

- (IBAction) closeSheetWithOK: (id) sender
{
    [NSApp endSheet: editingPanel];
    [editingPanel orderOut: self];
    [comboBoxValues setArray: valuesCopy];
    if (comboBoxValues.count > 0)
        [editedComboBox setStringValue: [comboBoxValues objectAtIndex: 0]];
    [self release];
}


- (IBAction) closeSheetWithCancel: (id) sender
{
    [NSApp endSheet: editingPanel];
    [editingPanel orderOut: self];
    [self release];
}

这是关闭工作表的唯一两个按钮。我的问题是关于实例的生命周期管理。它在类方法中分配,但随后控制再次传递给Cocoa,类方法结束。我发现释放实例的唯一地方是关闭按钮的两个处理程序。我的问题是beginSheet:modalForWindow:modalDelegate:didEndSelector:contextInfo:不是简单地打开工作表,然后等待它再次关闭,返回一个值如何关闭。如果是这种情况,我可以在类方法中关闭实例,我会感觉更好。

我的问题:是否有更好的方法来处理实例的生命周期,或者Cocoa中有什么东西允许我以模态方式打开工作表窗口然后等待它再次关闭,所以我可以释放实例就在那之后?我想不出任何,但毕竟我是一个相对的新手。

FWIW,代码有效,所以没有错误。我对我在类方法中分配的构造不太满意,然后必须在它自己的两个实例方法中释放它。

3 个答案:

答案 0 :(得分:2)

在我看来,这不应该是一种类方法,而你定义生命周期的问题是一个警告信号,表明它是在没有明确所有权的情况下创建的。

答案 1 :(得分:1)

  

我对我在类方法中分配的构造不太满意,然后必须在它自己的两个实例方法中释放它。

有一定的逻辑 - 但我还声称窗口模式表更自然地由实例方法启动。窗口毕竟是某个对象的表示,而不仅仅是一个类。

但这并没有回答你关于生命周期的更普遍的问题。

答案 2 :(得分:1)

我设法得到了令我满意的东西。我提供了beginSheet:在工作表结束后调用的方法,将控制器作为上下文信息。 IOW:

    [NSApp beginSheet: [controller window]
       modalForWindow: [aComboBox window]
        modalDelegate: controller
       didEndSelector: @selector(sheetDidEnd:returnCode:contextInfo)
          contextInfo: (void *)controller];
}

现在是两个按钮的代码:

- (IBAction) closeSheetWithOK: (id) sender
{
    [comboBoxValues setArray: valuesCopy];
    if (comboBoxValues.count > 0)
        [editedComboBox setStringValue: [comboBoxValues objectAtIndex: 0]];
    [NSApp endSheet: editingPanel];
}


- (IBAction) closeSheetWithCancel: (id) sender
{
    [NSApp endSheet: editingPanel];
}

并且sheetDidEnd:returnCode:contextInfo:的代码是:

- (void) sheetDidEnd: (NSWindow *) sheet returnCode: (NSInteger) returnCode contextInfo: (void *) contextInfo
{
    [sheet orderOut: (id)contextInfo];
    [(id)contextInfo release];
}

也就是IMO,这种情况可以做到最好。如果从窗口控制器的实例方法AFAICT调用它,则该过程将是相同的。