我有一个带有 NSOpenPanelaccessoryView ;在此 View 中,用户选择几个单选按钮来更改允许的类型。当面板打开时,启用正确的文件,禁用其他文件。好的,很好。

现在用户更改了单选按钮,accessoryView 的 viewController 观察单选按钮矩阵的变化,并因此更改 NSOpenPanel 的 allowedTypes

之后,按照 Apple 文档,它调用 -validateVisibleColumns ,但面板中没有任何可见的变化。那就是:正确的文件似乎被禁用了:我可以选择它们,但它们是灰色的!
另一个错误效果:我选择了一个文件(启用),更改文件类型,(现在错误的)文件保持选中状态,启用了确定按钮:但这是错误的文件类型!似乎发生了变化但界面不知道!

我的代码是(选择绑定(bind)到单选按钮矩阵):

- (void)observeValueForKeyPath.....
{
    NSString *extension = (self.selected==0) ? @"txt" : @"xml";
    [thePanel setAllowedFileTypes:@[extension, [extension uppercaseString]]];
    [thePanel validateVisibleColumns];
}

我首先尝试插入调用
[thePanel displayIfNeeded]

然后我试过
[thePanel contentView] setNeedsDisplay]

没有结果。我还尝试实现面板委托(delegate)方法 panel:shouldEnableURL: ,应该由 validateVisibleColumns 调用:我刚刚发现它在 NSOpenPanel 的打开时只被调用了一次。

有人可以知道为什么会发生这种情况吗?我用沙盒和非沙盒应用程序尝试了所有这些,没有区别。我正在使用 10.8 sdk 在 ML 上进行开发。

编辑

现在避免这个问题的唯一方法是实现 panel:validateURL:error ,但这是在用户单击“打开”后调用的,这非常糟糕。

最佳答案

我有完全相同的问题,在 10.9 下,非沙盒化,并且在这一天的大部分时间里都在试图找到解决方案!

在对构成 NSOpenPanel 的各种类进行了大量修改和深入研究后(确实是 NSSavePanel),我确实找到了一种方法来强制底层表自行刷新:

id table = [[[[[[[[[[[[_openPanel contentView] subviews][4] subviews][0] subviews][0] subviews][0] subviews][7] subviews][0] subviews][1] subviews][0] subviews][0] subviews][0] subviews][2];
[table reloadData];

当然,编写此 hack 的最佳方法是遍历 subview 列表,确保找到正确的类,并最终为后续的 reloadData 调用缓存结束表 View 。

我知道,我知道,这是一个非常丑陋的组合,但是,除了“提交错误报告”之外,我似乎找不到任何其他答案来解决该问题。其中,从我所看到的网上人们自 1.8 以来一直在做什么! :(

编辑:
这是我现在用来使我的 NSOpenPanel 在 10.9 下正确运行的代码:
- (id) openPanelFindTable: (NSArray*)subviews;
{
    id table = nil;

    for (id view in subviews) {
        if ([[view className] isEqualToString: @"FI_TListView"]) {
            table = view;
            break;
        } else {
            table = [self openPanelFindTable: [view subviews]];
            if (table != nil) break;
        }
    }

    return table;
}


- (void) refreshOpenPanel
{
    if (_openPanelTableHack == nil)
        _openPanelTableHack = [self openPanelFindTable: [[_openPanel contentView] subviews]];
    [_openPanelTableHack reloadData];
    [_openPanel validateVisibleColumns];
}

此代码需要声明两个实例变量 _openPanel_openPanelTableHack 才能工作。我将 _openPanel 声明为 NSOpenPanel* 并且 _openPanelTableHack 声明为 id

现在,我不是调用 [_openPanel validateVisibleColumns],而是调用 [self refreshOpenPanel] 来强制面板按预期更新文件名。我尝试在创建 NSOpenPanel 时缓存表 View ,但是,似乎一旦您“运行”面板,表 View 就会更改,因此我必须在第一次更新时缓存它。

同样,这是一个 GIANT hack,但是,我不知道 Apple 需要多长时间才能解决附件 View 和文件面板的问题,所以现在,这是有效的。

如果有人有任何其他不是大杂烩的解决方案,请分享! ;)

关于objective-c - NSOpenPanel(不)validateVisibleColumns,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/18192986/

10-12 18:34