macOS UI 对话框!开启面板时忽略套件(Package)目录

对话框!开启面板时忽略套件(Package)目录

先前文章对话框!开启与储存面板功能已经理解如何使用NSOpenPanelNSSavePanel方法,不过值得注意的是,当你设定只能选择档案类型时setCanChooseFiles:YES,被封装(package)类型的也会被视为单一档案(其实它是目录组成的),像我们使用的.app档案、.Bundle档案这些都是用目录组成的。

Finder上选择档案后按下右键时会提示你要不要显示套件内容

选择就会进入该目录看到整个结构,如果你不选择时,Mac中会使用预设的解析程式去解析套件内容并执行主程式将App开启,但从上面描述中能了解,它并不是真正的档案,接下来要将这种目录类型的套件在开启面板中忽略,让使用者无法去选择这类型的档案。

NSOpenSavePanelDelegate

开启与储存面板功能提供了Delegate,名为:NSOpenSavePanelDelegate,如此一来可以使用Delegate在开启面板功能时能立即的接收到该物件的资料,并且将资料做一些预处理功能。

每当开启面板时,会立即执行Delegate:- (BOOL)panel:(id)sender shouldEnableURL:(NSURL *)url,询问读到的档案、目录名称是否接受在列表上面能够被选择(档案、目录),不想要被使用者选择时只要返回YES,之后就会在列表上显示灰色代表不能被选择:

上图为经过处理后的列表,此功能将套件目录不能被使用者所选择,所以呈现灰色,完整的程式如下:

//-----------start-----------
//使用前记得在标头档中加入NSOpenSavePanelDelegate
//<NSOpenSavePanelDelegate>
//
- (BOOL)panel:(id)sender shouldEnableURL:(NSURL *)url
{
    BOOL showObject = YES;

    NSString *filename = [url relativePath];
    NSError *error;
    NSDictionary* fileAttribs = [[NSFileManager defaultManager] attributesOfItemAtPath:[url relativePath] error:&error];//取得档案/目录 名称的属性

    if (fileAttribs)
    {
        // check for packages
        if ([NSFileTypeDirectory isEqualTo:[fileAttribs objectForKey:NSFileType]])//判断选择的名称是否为目录结构
        {
            if ([[NSWorkspace sharedWorkspace] isFilePackageAtPath:filename] == NO)//再判断路径名称是否为套件目录
                showObject = YES;//返回YES代表不接受被选择(呈灰色)
            else
                showObject = NO;//返回YES代表接受被选择
        }
        else
        {
            showObject = YES;//返回YES代表不接受被选择(呈灰色)
        }
    }
    return showObject;
}
//------------end------------

此程式有参考Apple官方的NSOpenPanel – Choosing any file and ignoring packages,但因使用的Delegate在10.5后就不支援,所以将它改用新的Delegate并且将使用的相关物件方法都更正并支援OSX 10.9。

参考资料

NSOpenPanel – Choosing any file and ignoring packages