基于NSDocument的应用如何在NSSavePanel中设置默认选中文件类型
问题描述

我正在使用NSDocument类开发一款简单的文档类应用,我的info.plist中配置了四个文档内容类型标识符,包括public.text、public.plain-text、public.source-code、public.rtf,如上图所示。调用NSSavePanel保存面板时,会列出所有上述文件类型,如下图所示:
我的问题是:是否可以通过代码指定保存面板弹出时默认选中的文件类型?我希望保存面板出现时默认选中「富文本(RTF)」类型。
以下是我的NSDocument子类的部分代码:
import Cocoa class Document: NSDocument { override init() { super.init() } override class var autosavesInPlace: Bool { return false } override func save(withDelegate delegate: Any?, didSave didSaveSelector: Selector?, contextInfo: UnsafeMutableRawPointer?) { if let _ = fileURL { print("Saved!!!") } else { print("Not saved yet...") NSApp.sendAction(#selector(NSDocument.saveAs(_:)), to: nil, from: self) } } override func writableTypes(for saveOperation: NSDocument.SaveOperationType) -> [String] { return super.writableTypes(for: saveOperation) } override func prepareSavePanel(_ savePanel: NSSavePanel) -> Bool { savePanel.allowsOtherFileTypes = true savePanel.isExtensionHidden = false guard let accessoryView = savePanel.accessoryView else { return true } for sub in accessoryView.subviews { print("Class: \(sub.className)") /* if sub.isKind(of: NSPopUpButton.self) { if let popUpButton = sub as? NSPopUpButton { popUpButton.selectItem(at: 5) print("Sure") } } */ } return true } }
我看到有一个类似主题的问题,其中使用了IKSaveOptions实现默认类型选择,但根据官方文档说明,该类仅适用于图像数据保存场景,而我的应用是文本类应用,不适用该方案,请问该如何实现需求?
解决方案
你不需要通过遍历保存面板私有子视图的方式修改选中项,这种方案依赖系统内部视图结构,系统版本更新后很容易失效,以下是两种官方支持的实现方式:
方式1:调整可写类型顺序(兼容所有 macOS 版本)
NSSavePanel 默认会选中 writableTypes(for:) 方法返回数组的第一个对应的文件类型,你只需要调整返回数组的顺序,把 RTF 对应的 UTI 放到第一位即可:
override func writableTypes(for saveOperation: NSDocument.SaveOperationType) -> [String] { let allTypes = super.writableTypes(for: saveOperation) // 把RTF类型移到数组首位 guard let rtfIndex = allTypes.firstIndex(of: "public.rtf") else { return allTypes } var orderedTypes = allTypes let rtfType = orderedTypes.remove(at: rtfIndex) orderedTypes.insert(rtfType, at: 0) return orderedTypes }
方式2:直接设置选中内容类型(适用于 macOS 11+)
如果你的应用最低支持 macOS 11,可以直接在 prepareSavePanel 中设置 selectedContentType 属性实现指定默认类型,逻辑更直观:
首先在文件头部导入 UniformTypeIdentifiers 框架:
import UniformTypeIdentifiers
然后修改 prepareSavePanel 方法:
override func prepareSavePanel(_ savePanel: NSSavePanel) -> Bool { savePanel.allowsOtherFileTypes = true savePanel.isExtensionHidden = false // 直接指定默认选中的RTF类型 if let rtfType = UTType("public.rtf") { savePanel.selectedContentType = rtfType } return true }
内容的提问来源于stack exchange,提问作者El Tomato
相关产品推荐
相关产品推荐

