###前置き###
前回、テキストエディタをサンプルとして、Document Based Applicationを作成する話をしましたが、それのStoryboard版です。私は、アプリケーション開発の目標として、日本語専門の、縦書きワードプロセッサを考えています。その第一のコンセプトは、フルスクリーンモードで、Macのディスプレイサイズが大きかろうが小さかろうが、一画面に表示する文字数とレイアウトは、常に同じにしたいと考えています。なので、編集モード、ドラフトモード、環境設定ダイアログなどは、別ウインドウを開くのではなく、画面遷移で実装することになるでしょう。ならば、Storyboardによる編集は、必然になると思われます。
###Xcodeで編集開始(ここから10分間)###
(1) Xcode 8で、新規プロジェクトを作成します。テンプレートは、macOSのCocoa Applicationです。
(2) プロジェクト設定で、Use Storyboardsと、Create Document-Based Applicationにチェックを入れます。今回は、プレーンテキストを保存するテキストエディタを作成するので、Document Extension(拡張子)をtxtとします。
(3) Main.storyboardを開きます。View ControllerにText Viewを貼り付けます。Text Viewを、ViewController.swiftの**@IBOutlet var textView: NSTextView!**にコネクトします。
(4) Document.swiftを開きます。下のように編集します。テンプレートに対して、新規に追加したコードを、// ↓↓↓↓↓↓
と// ↑↑↑↑↑↑
で挟んで、示しています。
import Cocoa
class Document: NSDocument {
// ↓↓↓↓↓↓
var viewController: ViewController?
var text: String?
// ↑↑↑↑↑↑
override init() {
super.init()
}
override class func autosavesInPlace() -> Bool {
return true
}
override func makeWindowControllers() {
let storyboard = NSStoryboard(name: "Main", bundle: nil)
let windowController = storyboard.instantiateController(withIdentifier: "Document Window Controller") as! NSWindowController
self.addWindowController(windowController)
// ↓↓↓↓↓↓
viewController = windowController.contentViewController as? ViewController
if let viewController = self.viewController, let text = self.text {
viewController.textView.string = text
}
// ↑↑↑↑↑↑
}
override func data(ofType typeName: String) throws -> Data {
// ↓↓↓↓↓↓
text = viewController?.textView.string
if let data = text?.data(using: .utf8) {
return data
}
// ↑↑↑↑↑↑
throw NSError(domain: NSOSStatusErrorDomain, code: unimpErr, userInfo: nil)
}
override func read(from data: Data, ofType typeName: String) throws {
// ↓↓↓↓↓↓
if let text = String(data: data, encoding: .utf8) {
self.text = text
return
}
// ↑↑↑↑↑↑
throw NSError(domain: NSOSStatusErrorDomain, code: unimpErr, userInfo: nil)
}
}
前回は、コードに対する説明を省きましたが、すこしだけ説明をつけておこうと思います。
Text Viewのテキストを、ファイル保存するのは、data(ofType typeName: String) throws -> Data
で行いますが、逆にファイルを開いて、Text Viewのテキストに入力するのは、ファイル読み込みのメソッドread(from data: Data, ofType typeName: String) throws
で行うわけではないことに、注目してください。このメソッドが実行された時点では、まだウインドウが開いていないので、Text Viewのテキストに代入しようがないのです。そこで、いったんプロパティtext: String?
に代入しておいて、ウインドウを開くメソッドmakeWindowControllers()
にて、Text Viewのテキストに代入します。