4

我有一个使用多个模式表进行数据输入的应用程序。打开模态表的方法运行良好,并且仍然运行良好,但它们已被弃用,我担心它们很快将不适用于 Xcode 的未来版本。 在这里,Apple 指出了如何使用模态表

    - (void)showCustomSheet: (NSWindow *)window

// User has asked to see the custom display. Display it.
{
    if (!myCustomSheet)
//Check the myCustomSheet instance variable to make sure the custom sheet does not already exist.
        [NSBundle loadNibNamed: @"MyCustomSheet" owner: self];

    [NSApp beginSheet: myCustomSheet
            modalForWindow: window
            modalDelegate: self
            didEndSelector: @selector(didEndSheet:returnCode:contextInfo:)
            contextInfo: nil];

    // Sheet is up here.
    // Return processing to the event loop
}

但随着 Xcode 5.1 的发布,他们发现 loadNibNamed 方法已被弃用,我们应该使用引用顶级对象的类似函数。

我遇到的问题是改变这个:

[NSBundle loadNibNamed:@"OrderDetailsWindow" owner:self];

进入这个。

NSArray *array;
[[NSBundle mainBundle]loadNibNamed:@"OrderDetailsWindow" owner:self topLevelObjects:&array]; 

此方法调用实际上确实打开了模式表。但是,在我打开模态表的方法结束时,Xcode 会因为这个错误而挂断。

0x7fff8c33b097:  andl   24(%r11), %r10d    Thread1: EXC_BAD_ACCESS (code:EXC_I386_GPFLT)

我不确定这是在告诉我什么。它没有在调试区域给我任何信息。这可能与未正确释放 topLevelObjects 数组有关吗?关于如何使这项工作更顺利一点的任何想法?Apple 过时的库快把我逼疯了!

4

2 回答 2

4

是的,Apple 的文档一团糟。“工作表编程主题”文档自 2009 年以来未更新。

更改后您没有显示完整的代码,但我的猜测是您的问题在于您的 NIB 对象的内存管理。

从新的文档loadNibNamed:owner:topLevelObjects:

与传统方法不同,对象遵循标准的可可内存管理规则;有必要通过使用 IBOutlets 或持有对数组的引用来保持对它们的强引用,以防止 nib 内容被释放。

顶级对象的出口应该是强引用,以证明所有权并防止重新分配。

你有一个 NSArray,它在你的方法中保存了顶级对象。一旦执行离开此方法, NSArray 将被取消引用并释放,如果在其他任何地方没有强烈引用这些顶级对象,则所有顶级对象也是如此。

您需要将 NIB 中的顶级对象连接到窗口控制器中的插座,或者将 NSArray 作为窗口控制器实例的成员变量,因此一旦显示方法的工作表退出,它就不会被释放。并确保 myCustomSheet 从工作表的 NIB 正确声明和连接。

此外,[NSApp beginSheet:]也已弃用,您现在在 NSWindow 的实例上调用 beginSheet

于 2013-10-31T15:25:53.527 回答
0

我总是NSWindowController为我的工作表使用带有自定义委托的子类:

从要显示工作表的窗口中:

_myModalController = [[MyModalController alloc] init];
_myModalController.delegate = self;
[_myModalController beginSheet:self.window];

然后在模态窗口控制器中,我有:

- (id)init {
    self = [super initWithWindowNibName:@"MyModalWindow" owner:self];
    return self;
}

- (void)beginSheet:(NSWindow *)mainWindow {
    [NSApp beginSheet:[self window]
       modalForWindow:mainWindow
        modalDelegate:self
       didEndSelector:@selector(_didEndSheet:returnCode:contextInfo:)
          contextInfo:nil];
}

- (void)endSheet:(NSWindow *)mainWindow {
    [NSApp endSheet:[self window]];
    [[self window] orderOut:mainWindow];
}

这似乎避免了loadNibNamed:被弃用的整个问题。

于 2013-10-31T15:38:08.447 回答