DearMiku

Mac开发---NSDocument

字数统计: 1.5k阅读时长: 5 min
2017/12/29 Share

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
37
import 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
2
NSDocumentController.shared.newDocument(nil)
//也可以直接init一个Document,然后加进去

打开

1
2
3
4
//用户通过面板打开一个新的Document 
NSDocumentController.shared.openDocument(nil)

//这里也可以使用NSDocument的init方法创建(使用的重载方法不同),但是这样创建的对象不再NSDocumentController的管理内~ 可以手动加入其中

保存

1
2
3
4
5

//保存所有文档
NSDocumentController.shared.saveAllDocuments(nil)

//也可以调用NSDocument的save方法

导出

1
这里应该调用的是 Document的 saveAs()/saveTo() 方法, 为了工整一些 我就放在这里了~

info.plist配置

NSDocument类支持的文档类型和导出的文档类型是在 info.plist中存储的~ 我们可以在Targets->info中进行设置~ 需要对Document TypeExport UTIs进行设置~~

screenshot

这里就引入了一个概念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上时,在新建的文档保存/导出时,会让我们选择格式~
screenshot

Export UTLs

若是App只是使用已有的文档类型如jpg,则是在Document Types中设置就已经足够了,但是若要试用自定义类型的话,则需要用到

screenshot

这里就简单展示了一下自定义类型,需要注意的是 上面除了Description外都是必填的~

identiferExtension这里是自定以的~怎么写都好~ 但是上下要一致

Conforms To这里我填写的是public.data,这里到底写什么,可以在UTIs中按需选择~

效果如下~~
miku

FileWrapper

有些时候,我们的文档并非只是一个文档,还有类似于bundle这种类型的文档包,(在这里吐槽一句,其实MarkDown也应该做成文档包这种样式就好了~) 效果如下
wrap

配置FileWrapper和上面略有不同~

infor配置

screenshot

主要就是将Conforms To改一下~ 然后在Document中实现对应的NSFileWrape方法 其他地方也就是换汤不换药

1
2
3
4
5
6
7
8
9
10
11
12
13
//保存时调用
override func fileWrapper(ofType typeName: String) throws -> FileWrapper {
let fileWrappers = FileWrapper(directoryWithFileWrappers: [:])

return fileWrappers
}

//读取时调用~ 包中的数据可以通过 filleWraper
override func read(from fileWrapper: FileWrapper, ofType typeName: String) throws {
for item in fileWrapper.fileWrappers! {
Swift.print("获得\(item.key)")
}
}

总结

NSDocument是 对文档的封装,无论面对什么样的文档 都是NSDocument对象,和 NSData一样~ 这种设计方案是是值得我们借鉴的 尤其是在写SDK时~

若上文有不准确的地方 还望多多指正 共同学习 (๑•ᴗ•๑)

CATALOG
  1. 1. Mac开发—NSDocument
  2. 2. 简述
  3. 3. NSDocument
  4. 4. NSDocumentController
    1. 4.1. 新建
    2. 4.2. 打开
    3. 4.3. 保存
    4. 4.4. 导出
  5. 5. info.plist配置
    1. 5.1. Document Types
    2. 5.2. Export UTLs
  6. 6. FileWrapper
    1. 6.1. infor配置
  7. 7. 总结