macOS保存文件的对话框NSSavePanel
macOS保存文件的对话框NSSavePanel

macOS保存文件的对话框NSSavePanel

NSSavePanel 是 AppKit 提供的类,在 macOS 中用于保存文件时弹出的系统对话框,允许用户选择保存路径、文件名、文件类型等。

基本用法

let savePanel = NSSavePanel()
savePanel.allowedFileTypes = ["txt"]
savePanel.nameFieldStringValue = "MyFile"
savePanel.canCreateDirectories = true

savePanel.begin { response in
    if response == .OK {
        if let url = savePanel.url {
            // 在这里保存文件内容到 url 路径
            try? "Hello, world!".write(to: url, atomically: true, encoding: .utf8)
        }
    }
}

常用属性

1、allowedFileTypes:允许保存的文件类型扩展名,如 [“jpg”, “png”]。

panel.allowedFileTypes = ["txt", "md"]

只允许保存为 .txt 或 .md 类型文件。

如果在保存文件的时候,填写的文件名不在文件类型扩展列表中,默认以首个文件类型保存。

当文件类型扩展名设置为[“txt”,”md”],保存文件为MyFile.png时,实际保存的文件名称为MyFile.png.txt。

2、nameFieldStringValue:默认的文件名。       

panel.nameFieldStringValue = "MyDocument.txt"

面板打开时默认文件名为 “MyDocument.txt”。

3、directoryURL:默认保存位置(URL),是一个 URL 类型的目录地址。

panel.directoryURL = FileManager.default.homeDirectoryForCurrentUser

可以设置directoryURL,选择打开的目录地址。

4、canCreateDirectories:是否允许新建文件夹。

panel.canCreateDirectories = true

用户可点击“新建文件夹”按钮。

5、isExtensionHidden:是否隐藏扩展名(默认 false)。

panel.isExtensionHidden = true

文件名输入框中不显示扩展名(如 .txt)。

6、message:顶部提示信息。

panel.message = "请选择保存位置和文件名"

会显示在面板顶部、按钮上方。

7、prompt:按钮文字(默认是“保存”)。

panel.prompt = "导出"

按钮会显示为“导出”而不是“保存”。

8、title:面板窗口的标题。

panel.title = "保存图片"

9、showsTagField:是否显示 macOS 的“标签”字段。

panel.showsTagField = true

macOS Ventura (13) 及以后系统中,showsTagField = false 在系统层面上被忽略,即使设置为 false,标签字段仍然会显示。这是 macOS 的行为变化,Apple 没有提供禁用标签字段的公开方式。

目前无正式方式隐藏标签字段,Apple 没有提供任何 API 来彻底关闭这个 UI 元素。如果想保持 UI 简洁,只能接受它显示,或者等待未来 macOS 系统可能做出改变。

10、treatsFilePackagesAsDirectories:是否将文件包(如 .app、.pages 文件)当作普通文件夹显示。

panel.treatsFilePackagesAsDirectories = false

11、isExpanded:初始时是否展开面板(显示侧边栏等)。

print(“panel.isExpanded”)

isExpanded是只读属性,可以根据isExpanded判断是否展开面板。

虽然 isExpanded 是只读属性,但可以通过 KVC 强制展开 NSSavePanel:

let panel = NSSavePanel()

// 使用 KVC 强制设置为展开状态
panel.setValue(true, forKey: "isExpanded")

// 其他常规设置
panel.allowedFileTypes = ["txt"]
panel.nameFieldStringValue = "example.txt"

if panel.runModal() == .OK {
    if let url = panel.url {
        print("保存到:\(url.path)")
    }
}

注意:这属于使用“私有 API”,虽然没风险但苹果没有官方保证此方式长期有效。

这个方法在 macOS 12、13、14(Ventura、Sonoma)中测试有效。

12、allowsOtherFileTypes:是否允许保存为未列在 allowedFileTypes 的扩展名。

panel.allowsOtherFileTypes = false

13、showsHiddenFiles:是否显示隐藏文件(macOS 中以点开头的文件)。

panel.showsHiddenFiles = true

异步与同步调用

异步方式(推荐,适用于 SwiftUI / Cocoa App):

savePanel.begin { response in ... }

同步方式(阻塞线程,适合简单用法):

if savePanel.runModal() == .OK {
    if let url = savePanel.url {
        // 保存文件
    }
}

使用场景

1、导出文件。

用户点击“导出”或“保存”按钮,弹出保存对话框。

func exportButtonClicked() {
    let savePanel = NSSavePanel()
    savePanel.allowedFileTypes = ["txt"]
    savePanel.nameFieldStringValue = "导出文件.txt"
    
    savePanel.begin { response in
        if response == .OK, let url = savePanel.url {
            try? "导出的内容".write(to: url, atomically: true, encoding: .utf8)
        }
    }
}

2、自定义格式文件(.myappdata)。

3、图片/日志/配置保存。

例如做了一个绘图应用,用户可以保存画布为 PNG。

let image = canvasView.snapshot() // 假设你生成了一个 NSImage
let savePanel = NSSavePanel()
savePanel.allowedFileTypes = ["png"]
savePanel.nameFieldStringValue = "MyDrawing.png"

savePanel.begin { response in
    if response == .OK, let url = savePanel.url {
        let tiffData = image.tiffRepresentation
        let bitmap = NSBitmapImageRep(data: tiffData!)
        let pngData = bitmap?.representation(using: .png, properties: [:])
        try? pngData?.write(to: url)
    }
}

4、快速提示用户自选位置保存临时文件。

总结

1、NSSavePanel:展示“保存文件”对话框。

2、NSOpenPanel:展示“打开文件”对话框。

3、推荐方法:begin { response in … }(非阻塞)。

相关文章

1、Swift 管理文件的FileManager类:https://fangjunyu.com/2024/11/03/swift-%e7%ae%a1%e7%90%86%e6%96%87%e4%bb%b6%e7%9a%84filemanager%e7%b1%bb/

2、Swift URL.documentsDirectory和FileManager 类的关系:https://fangjunyu.com/2024/11/03/swift-url-documentsdirectory%e5%92%8cfilemanager-%e7%b1%bb%e7%9a%84%e5%85%b3%e7%b3%bb/

   

如果您认为这篇文章给您带来了帮助,您可以在此通过支付宝或者微信打赏网站开发者。

欢迎加入我们的 微信交流群QQ交流群,交流更多精彩内容!
微信交流群二维码 QQ交流群二维码

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注