最近在寫的App是這種類型的,總結了總結,寫了這篇博文,在掘金中沒有客戶端分類 我不知道該放到那個分類裏 就放在iOS裏吧html
本文旨在介紹如何實現 基於文檔的Mac App 如有描述不許確或錯誤的地方 還望多多指正,共同窗習(๑•ᴗ•๑)api
實現的效果也就是 在文檔的打開方式中有本身的App可選,將文件拖拽至Dock欄中能夠打開~bash
NSDocument
類至關於一層封裝~ ,相似於UIImage
,不管是jpg格式仍是png格式都以UIImage
對象進行調用~app
NSDocument
則不只能夠對外持有 文檔數據, 對內能夠綁定 窗口控制器~.當打開文檔時自動建立並展現與其綁定的窗口控制器~dom
Xcode提供的Document模板大概就是下面這個樣子~ide
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))
}
}
複製代碼
顧名思義是負責對Document
進行管理,是一個單例~ 方法也就主要是下面這些~學習
NSDocumentController.shared.newDocument(nil)
//也能夠直接init一個Document,而後加進去
複製代碼
//用戶經過面板打開一個新的Document
NSDocumentController.shared.openDocument(nil)
//這裏也能夠使用NSDocument的init方法建立(使用的重載方法不一樣),可是這樣建立的對象再也不NSDocumentController的管理內~ 能夠手動加入其中
複製代碼
//保存全部文檔
NSDocumentController.shared.saveAllDocuments(nil)
//也能夠調用NSDocument的save方法
複製代碼
這裏應該調用的是 Document的 saveAs()/saveTo() 方法, 爲了工整一些 我就放在這裏了~
複製代碼
對NSDocument
類支持的文檔類型和導出的文檔類型是在 info.plist
中存儲的~ 咱們能夠在Targets->info中進行設置~ 須要對Document Type和Export UTIs進行設置~~ui
這裏就引入了一個概念UTI,它是Apple系統處理文檔文件等數據的統一類型標識符,也能夠把它理解爲蘋果爸爸對其餘各種文檔數據的別名,你們叫jpg
,蘋果爸爸叫它public.jpeg
.除去UTI中約定好的部分,對於 咱們自創的類型,則能夠設置自創的別名~ 在這裏我就使用已有類型了jpg
其餘的UTI看這裏Uniform Type Identifiesspa
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上時,在新建的文檔保存/導出時,會讓咱們選擇格式~
如果App只是使用已有的文檔類型如jpg
,則是在Document Types中設置就已經足夠了,可是若要試用自定義類型的話,則須要用到
Description
外都是必填的~
identifer和Extension這裏是自定以的~怎麼寫都好~ 可是上下要一致
Conforms To這裏我填寫的是public.data
,這裏到底寫什麼,能夠在UTIs中按需選擇~
效果以下~~
有些時候,咱們的文檔並不是只是一個文檔,還有相似於bundle
這種類型的文檔包,(在這裏吐槽一句,其實MarkDown也應該作成文檔包這種樣式就行了~) 效果以下
配置FileWrapper和上面略有不一樣~
NSFileWrape
方法 其餘地方也就是換湯不換藥
//保存時調用
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時~
若上文有不許確的地方 還望多多指正 共同窗習 (๑•ᴗ•๑)