13
10

More than 5 years have passed since last update.

[macOS] 超速!10分間で、テキストエディタを作る。Storyboard版。

Posted at

前置き

前回、テキストエディタをサンプルとして、Document Based Applicationを作成する話をしましたが、それのStoryboard版です。私は、アプリケーション開発の目標として、日本語専門の、縦書きワードプロセッサを考えています。その第一のコンセプトは、フルスクリーンモードで、Macのディスプレイサイズが大きかろうが小さかろうが、一画面に表示する文字数とレイアウトは、常に同じにしたいと考えています。なので、編集モード、ドラフトモード、環境設定ダイアログなどは、別ウインドウを開くのではなく、画面遷移で実装することになるでしょう。ならば、Storyboardによる編集は、必然になると思われます。

Xcodeで編集開始(ここから10分間)

(1) Xcode 8で、新規プロジェクトを作成します。テンプレートは、macOSのCocoa Applicationです。
(2) プロジェクト設定で、Use Storyboardsと、Create Document-Based Applicationにチェックを入れます。今回は、プレーンテキストを保存するテキストエディタを作成するので、Document Extension(拡張子)をtxtとします。

option.png

(3) Main.storyboardを開きます。View ControllerにText Viewを貼り付けます。Text Viewを、ViewController.swift@IBOutlet var textView: NSTextView!にコネクトします。
(4) Document.swiftを開きます。下のように編集します。テンプレートに対して、新規に追加したコードを、// ↓↓↓↓↓↓// ↑↑↑↑↑↑で挟んで、示しています。

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のテキストに代入します。

13
10
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
10