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