首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >NSOpenPanel (不) validateVisibleColumns

NSOpenPanel (不) validateVisibleColumns
EN

Stack Overflow用户
提问于 2013-08-12 17:24:09
回答 3查看 799关注 0票数 3

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

现在用户改变单选按钮,accessoryView的accessoryView观察单选按钮矩阵中的变化,从而改变NSOpenPanel的allowedTypes

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

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

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

我第一次尝试插入一个电话

代码语言:javascript
复制
[thePanel displayIfNeeded]

然后我试着

代码语言:javascript
复制
[thePanel contentView] setNeedsDisplay]

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

有人能知道为什么会这样吗?我尝试了所有这些沙箱和非沙箱应用程序,没有区别。我正在使用10.8SDK开发ML。

编辑

到目前为止,避免这个问题的唯一方法是实现panel:validateURL:error,但是这是在用户单击“open”之后调用的,这是非常糟糕的。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-01-22 17:33:19

我有完全相同的问题,在10.9以下,非沙箱,并花了这一天的大部分时间试图找到一个解决方案!

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

代码语言:javascript
复制
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];

当然,编写此黑客代码的最佳方法是沿着子视图列表走下去,确保找到正确的类,并最终为后续的reloadData调用缓存结束表视图。

我知道,我知道,这是一个非常丑陋的传说,然而,我似乎找不到任何其他的答案来解决这个问题,除了“提交一个错误报告”。据我所见,网上的人从1.8开始就一直在做这件事!

编辑:这里是我现在用来使我的NSOpenPanel在10.9下正确运行的代码:

代码语言:javascript
复制
- (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时,我尝试过缓存表视图,但是,一旦您“运行”面板,表视图就会发生变化,所以我必须在第一个更新时缓存它。

再次,这是一个巨大的黑客,然而,我不知道苹果将需要多长时间来解决问题的附件视图和文件面板,因此,目前,这是可行的。

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

票数 5
EN

Stack Overflow用户

发布于 2015-03-13 11:16:41

Eidola解决方案的快速实现。最大的区别是我搜索的是一个NSBrowser (子)类,而不是一个特定的类名。测试在10.10 (不是沙箱)。

代码语言:javascript
复制
private weak var panelBrowser : NSBrowser? //avoid strong reference cycle
func reloadBrowser()
{
    if let assumedBrowser = panelBrowser
    {
        assumedBrowser.reloadColumn(assumedBrowser.lastColumn)
    }
    else if let searchResult = self.locateBrowser(self.panel?.contentView as! NSView)
    {
        searchResult.reloadColumn(searchResult.lastColumn)
        self.panelBrowser = searchResult //hang on to result
    }
    else
    {
        assertionFailure("browser not found")
    }
}

//recursive search function
private func locateBrowser(view: NSView) -> NSBrowser?
{
    for subview in view.subviews as! [NSView]
    {
        if subview is NSBrowser
        {
            return subview as? NSBrowser
        }
        else if let result = locateBrowser(subview)
        {
            return result
        }
    }
    return nil
}

编辑:

好的,所以上面的代码不会一直工作。如果它不工作,并且选择了一个文件(您可以看到详细信息/预览),那么您必须重新加载最后一列而不是最后一列。要么重新加载最后两列(确保至少有2列),要么重新加载所有列。

第二个问题:如果重新加载列,则会丢失所选内容。是的,所选的文件/目录仍将被高亮显示,但是面板将不会返回正确的URL。

现在我使用这个函数:

代码语言:javascript
复制
func reloadBrowser()
{
    //obtain browser
    if self.panelBrowser == nil
    {
        self.panelBrowser = self.locateBrowser(self.panel?.contentView as! NSView)
    }
    assert(panelBrowser != nil, "browser not found")

    //reload browser
    let panelSelectionPatch = panelBrowser.selectionIndexPaths //otherwise the panel return the wrong urls
    if panelBrowser.lastColumn > 0
    {
        panelBrowser.reloadColumn(panelBrowser.lastColumn-1)
    }
    panelBrowser.reloadColumn(panelBrowser.lastColumn)
    panelBrowser.selectionIndexPaths = panelSelectionPatch
}
票数 1
EN

Stack Overflow用户

发布于 2015-04-09 15:35:26

只需升级到xcode 6.3 (在约塞米蒂10.10.3上)就可以了。苹果修复了这个漏洞(不再需要Eidola )。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18192986

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档