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