用10.9打开模态表

时间:2013-10-25 22:58:29

标签: objective-c cocoa modal-dialog

我有一个使用多个模态表进行数据输入的应用。打开模态表的方法运行良好,仍然可以正常工作,但它们已经被弃用了,我担心它们很快就不能用于未来的Xcode版本。 Here, Apple points out how to use modal sheets

    - (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数组没有正确发布有关吗?关于如何使这项工作更顺利的任何想法?苹果公司过时的图书馆让我疯狂!

2 个答案:

答案 0 :(得分:4)

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

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

来自新loadNibNamed:owner:topLevelObjects:

的文档
  

与传统方法不同,对象遵循标准的可可内存   管理规则;有必要对它们进行有力的参考   通过使用IBOutlets或持有对数组的引用来防止   nib内容被解除分配。

     

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

您拥有保存方法中顶级对象的NSArray。一旦执行离开这个方法,NSArray就会被删除并释放,如果那些在其他任何地方都没有被强烈引用,那么你的所有顶级对象也是如此。

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

此外,[NSApp beginSheet:]也已弃用,现在请致电beginSheet on an instance of NSWindow

答案 1 :(得分: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:被弃用的整个问题。