macOS UI 對話框!開啟與儲存面板功能

用程式引用內建的開啟與儲存對話框(面板)功能

開啟與儲存對話框(面板)功能

撰寫Mac程式需要存檔或是開啟檔案時,會有一個介面與使用者互動,不過不用擔心自行要寫這個功能,因為Framework已經提供NSOpenPanelNSSavePanel框架使用,您可以依照您的情況去使用這兩項框架,如果您要讓使用者去選擇某個檔案或是選擇目錄時,那就能使用NSOpenPanel,如果是屬於要指定存檔的檔名時,就使用NSSavePanel

開啟檔案或指定目錄

達到這項功能需要使用NSOpenPanel,然而它是屬於對話框的方式,也就是與NSAlert用法類似,當然也提供了獨視窗模式合併視窗模式,這兩種模式的差別在於,合併視窗模式與原本的視窗是融合一體,並非是2個視窗的存在,依照使用情況可以自行選擇你要哪種類型。

獨立視窗模式

從圖中能明顯的看到獨立視窗是以原本的視窗再加上呼叫開啟對話框功能總共2個視窗,最基本的程式如下:

//-----------start-----------
    NSOpenPanel* panel = [NSOpenPanel openPanel];

    [panel beginWithCompletionHandler:^(NSInteger result){
        if (result == NSFileHandlingPanelOKButton) {
            NSURL*  theDoc = [[panel URLs] objectAtIndex:0];
            NSLog(@"%@",[theDoc relativeString]);
        }

    }];
//------------end------------

程式中使用beginWithCompletionHandler的method來啟動這個功能,另外還附加Block的方式在使用者選擇好時按下Button後,利用此結果來執行功能,其中選擇完的結果會回傳到result,回傳值會有:

  • NSFileHandlingPanelOKButton 按下Open也就是等於你的選擇已經確定之後
  • NSFileHandlingPanelCancelButton 按下Cancel取消功能

所以程式中會針對NSFileHandlingPanelOKButton後來取得選擇的檔案名稱,此時會已選擇的檔案名稱可以利用URLs來取得,回傳的是一個NSArray類型,但檔案路徑回傳格式使用NSURL回傳,NSURL功能可參照NSURL 裝載URL結構的物件,然而NSArray的大小是依照你選擇檔案的數量決定,不過不管你選擇的數量多少,範例程式只取NSArray的索引第0個,並且將檔案名稱印出來,可能會像這樣:

file:///Users/danny/Desktop/%E7%85%A7%E7%89%87%202014-7-9%20%E4%B8%8A%E5%8D%8810.34.jpg

因為以URL的格式呈現,路徑上會依照URL方式將一些字元轉換。

合併視窗模式

前面有介紹一些概念,應該大致上能了解怎麼使用,至於怎麼啟動成合併視窗模式的樣式,差別就在於最後的呼叫method beginSheetModalForWindow,在使用時你要傳入對話框要是哪個視窗合併,我們使用[self window]將現行視窗的物件傳入,所以將關鍵的程式更換成如下:

//-----------start-----------
    NSOpenPanel* panel = [NSOpenPanel openPanel];

    [panel beginSheetModalForWindow:[self window] completionHandler:^(NSInteger result){
        if (result == NSFileHandlingPanelOKButton) {
            NSURL*  theDoc = [[panel URLs] objectAtIndex:0];
             NSLog(@"%@",[theDoc relativeString]);
        }

    }];
//------------end------------

如此一來就產生合併視窗模式的對話框。

附加功能

基本的功能你只要用簡單的幾段程式就能啟動對話框,但其實還有許多細節能設定,例如:檔案類型、單選檔案、多選檔案…等,下面用一段程式並加上註解簡單的解說一下功能:

//-----------start-----------
    NSOpenPanel* panel = [NSOpenPanel openPanel];
    //屬性設置
    [panel setCanChooseDirectories:YES];//能否選目錄
    [panel setAllowsMultipleSelection:YES];//一次多選
    [panel setCanChooseFiles:YES];//能否選檔案
    [panel setCanHide:YES];//能否看見隱藏檔
    [panel setMessage:@"Message"];//功能說明
    [panel setTitle:@"Title"];//標題
    [panel setPrompt:@"OK"];//變更原本Open按鍵的名稱
    [panel setAllowedFileTypes:[NSImage imageTypes]];//限定檔案類型
    [panel setCanCreateDirectories:YES];//是否顯示新建目錄功能
//------------end------------

圖中將部分與對話框外觀有關的用圖示說明,其他的另外做說明:

  • setCanChooseDirectories 是否能選擇目錄,如果你的應用是選擇檔案的話這個項目就要選NO
  • setAllowsMultipleSelection 是否選多重選擇,如果你選擇YES,返回值就會存在陣列中,所以需要利用method [panel URLs]來處理
  • setCanChooseFiles 是否能選擇檔案,你的應用是要讓使用者決定哪個目錄,那就要選擇YES,相對的,setCanChooseDirectories那就必需要選擇NO
  • setCanHide 是否能看見隱藏檔,這由你選擇的檔案是不是能接受隱藏檔而定
  • setAllowedFileTypes 利用陣列傳入副檔名類型,如果符合傳入的類型,就能提供選擇,反之檔案名稱就會變灰色無法選擇

儲存檔案

儲存檔案的對話框之開啟檔案的對話框整個外觀上差別不大,主要是差在儲存檔案對話框具有輸入檔名及Tag的功能,開啟檔案對話框只能選擇檔案,檔案選擇可以單選或多選,所以整段啟動的程式碼差異不大,但顯示視窗也是分為2種顯示方式。

獨立視窗模式

//-----------start-----------
    NSSavePanel*    panel = [NSSavePanel savePanel];

    [panel beginWithCompletionHandler:^(NSInteger result){
        if (result == NSFileHandlingPanelOKButton) {
            NSURL*  theDoc = [panel URL];
            NSLog(@"%@",[theFile relativeString]);
        }

    }];

//------------end------------

合併視窗模式

//-----------start-----------
    NSSavePanel*    panel = [NSSavePanel savePanel];

    [panel beginSheetModalForWindow:[self window] completionHandler:^(NSInteger result){
        if (result == NSFileHandlingPanelOKButton) {
            NSURL*  theFile = [panel URL];
            NSLog(@"%@",[theFile relativeString]);
        }

    }];
//------------end------------

附加功能

儲存對話框所能用的Method大致上先前在開啟對話框所介紹的都能使用,這裡不再說明,下面要特別提出來的是setAllowedFileTypessetAllowsOtherFileTypes這兩個method,利用它可以限制使用者能存的檔名。

setAllowedFileTypes、setAllowsOtherFileTypes

如果你不做這項的設定,那使用者可以隨意的命名且檔案類型的副檔名也能自訂,檔案名稱輸入完成後不會有其他提示就能得到返回值,但你的應用如果是特殊用途必需要限制儲存的檔案類型的副檔名名稱,那你必需將你要支援的檔案類型的副檔名以陣列的方式傳入,像下面這樣:

[panel setAllowedFileTypes:@[@"png",@"jpg"]];

但你輸入的是超過1組的副檔名類型,輸入檔案名稱未輸入副檔名時,對話框自動補上副檔名功能會以陣列索引值第1個為主,在上面例子中索引值第1個為png,不過,如果你將檔名打成test.doc,對話框會自動認為要改變副檔名,此時自動補上副檔名功能會根據你對setAllowsOtherFileTypes的設定值而出現不同的提示訊息:

setAllowsOtherFileTypes:YES

你設定YES代表接受其他的檔案類型的檔名,所以輸入未在設定中的檔案類型時,就會出現提示問您是要使用預設的檔案類型或是您自行輸入的檔案類型:

  • Use .png 檔名就會取代doc變成test.png
  • Use .doc 檔名會維持原樣test.doc

setAllowsOtherFileTypes:NO

當你設定不接受其他檔案類型的輸入,但你在輸入檔名時多加副檔名名稱,對話框認為你要變更儲存的檔案類型的副檔名時就會跳出視窗讓您選擇:

  • Use Both 直接會輸入的檔案名稱後直接補上.png,檔名就會如提所說的test.doc.png

  • Use .png 對話框會自動將最後的副檔名取代成預設的副檔名,例子中則會用自行輸入的test.doc變更為test.png

範例程式

範例提供開啟與儲存對話框的使用,以及對話框視窗顯示的方式,可以參考程式內容視需要自行再做修改使用

範例程式

參考資訊

File System Programming Guide