Mac开发—NSDocument
简述
最近在写的App是这种这种类型的,总结了总结,写了这篇博文,本文旨在介绍如何实现 基于文档的Mac App 若有描述不准确或错误的地方 还望多多指正,共同学习(๑•ᴗ•๑)
实现的效果也就是 在文档的打开方式中有自己的App可选,将文件拖拽至Dock栏中可以打开~
NSDocument
NSDocument
类相当于一层封装~ ,类似于UIImage
,无论是jpg格式还是png格式都以UIImage
对象进行调用~
NSDocument
则不仅可以对外持有 文档数据, 对内可以绑定 窗口控制器~.当打开文档时自动创建并展示与其绑定的窗口控制器~
Xcode提供的Document模板大概就是下面这个样子~1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37import Cocoa
class Document: NSDocument {
var saveData:Data!
//是否自动保存(出用户选择外的所有保存方式 都是非自动保存,像按钮..点击的方法中可以保存,其他的不能)
override class var autosavesInPlace: Bool {
return true
}
//用于为Document绑定WindowController,当打开新的Document时,对应的WindowController就会被打开~(不绑定也是可以的)
override func makeWindowControllers() {
let storyboard = NSStoryboard(name: NSStoryboard.Name("Main"), bundle: nil)
let windowController = storyboard.instantiateController(withIdentifier: NSStoryboard.SceneIdentifier("Document Window Controller")) as! NSWindowController
self.addWindowController(windowController)
}
//将当前文档保存时调用
override func data(ofType typeName: String) throws -> Data {
Swift.print("保存文件")
return saveData
}
//当读取新的数据时调用
override func read(from data: Data, ofType typeName: String) throws {
saveData = data
Swift.print("读取内容 来自\(self.fileURL)")
}
//自动保存时调用的方法~ 当前是否能判断是否
override func autosave(withImplicitCancellability autosavingIsImplicitlyCancellable: Bool, completionHandler: @escaping (Error?) -> Void) {
Swift.print("调用自动保存")
//completionHandler(nil)
completionHandler(NSError.init(domain: "错误提示", code: 0, userInfo: nil))
}
}
NSDocumentController
顾名思义是负责对Document
进行管理,是一个单例~ 方法也就主要是下面这些~
新建
1 | NSDocumentController.shared.newDocument(nil) |
打开
1 | //用户通过面板打开一个新的Document |
保存
1 |
|
导出
1 | 这里应该调用的是 Document的 saveAs()/saveTo() 方法, 为了工整一些 我就放在这里了~ |
info.plist配置
对NSDocument
类支持的文档类型和导出的文档类型是在 info.plist
中存储的~ 我们可以在Targets->info中进行设置~ 需要对Document Type和Export UTIs进行设置~~
这里就引入了一个概念UTI,它是Apple系统处理文档文件等数据的统一类型标识符,也可以把它理解为苹果爸爸对其他各类文档数据的别名,大家叫jpg
,苹果爸爸叫它public.jpeg
.除去UTI中约定好的部分,对于 我们自创的类型,则可以设置自创的别名~ 在这里我就使用已有类型了jpg
其他的UTI看这里Uniform Type Identifies
Document Types
Name: 文档的类型名称,可为空~
identifer: 文档标识,若是用自定义的类型,这里可以写自定义的类型.若是针对已有类型可以在UTI中找~
Class: 标识该类型对应在项目中的Document类,我使用的继承NSDocument
的子类 MK_Document,所以这里填 $(PRODUCT_MODULE_NAME).MK_Document
Roler: 这里表示应用对文档的处理权限, Editor(读写),Viewer(只读).
Extensions: 文档后缀,不区别大小写~
Icon: 自定义类型在Finder中显示的样子(有时候可以,有时候不行,就和我用Movist看mkv
视频,有时候可以带上Movist图标,有时候不行~ 要有懂这个图片设置的老铁 分享一蛤~)
至于其他的一些选项,我没用到
至于下面那个additional document type properties
是设置额外的文档属性,在旧版Xcode中Document Types在这里的选项并没有这么多,那个时候需要用它设置额外的一些属性,我用的Xcode9上面提供的选项已经够用了~~
当我们设置多个Document Type且绑定至同一个Document上时,在新建的文档保存/导出时,会让我们选择格式~
Export UTLs
若是App只是使用已有的文档类型如jpg
,则是在Document Types中设置就已经足够了,但是若要试用自定义类型的话,则需要用到
这里就简单展示了一下自定义类型,需要注意的是 上面除了Description
外都是必填的~
identifer和Extension这里是自定以的~怎么写都好~ 但是上下要一致
Conforms To这里我填写的是public.data
,这里到底写什么,可以在UTIs中按需选择~
效果如下~~
FileWrapper
有些时候,我们的文档并非只是一个文档,还有类似于bundle
这种类型的文档包,(在这里吐槽一句,其实MarkDown也应该做成文档包这种样式就好了~) 效果如下
配置FileWrapper和上面略有不同~
infor配置
主要就是将Conforms To改一下~ 然后在Document中实现对应的NSFileWrape
方法 其他地方也就是换汤不换药
1 | //保存时调用 |
总结
NSDocument
是 对文档的封装,无论面对什么样的文档 都是NSDocument对象,和 NSData一样~ 这种设计方案是是值得我们借鉴的 尤其是在写SDK时~
若上文有不准确的地方 还望多多指正 共同学习 (๑•ᴗ•๑)