1

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

单击按钮调用在同一视图中找到组合框的代码,然后调用以下函数(的类方法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. 它控制一个面板,允许我编辑组合框中的列表(删除项目、排序项目等)。除了其他控件外,它还有两个关闭它的按钮,取消和确定。

两个按钮的代码是:

- (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,代码有效,所以没有错误。我对我在类方法中分配某些东西的构造不太满意,然后必须在其自身的两个实例方法中释放它。

4

3 回答 3

2

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

于 2011-07-22T19:15:46.340 回答
1

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

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

不过,这并没有回答您关于生命周期的更普遍的问题。

于 2011-07-22T19:15:29.947 回答
1

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

    [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 调用的,则该过程将是相同的。

于 2011-07-22T22:03:29.203 回答