[PencilKit]Webブラウザに直接メモを書き込めるアプリを作った

# イントロ

6月にあった WWDC 2019 でPencilKitが発表されました。

https://developer.apple.com/documentation/pencilkit/

これは純正メモアプリなどで使用されているペンツールをサードパーティーアプリでも使用できるようにするもので、Apple Pencil関連のアプリ開発のハードルが一気に下がります。

## PencilKit 概要

PencilKitの主なパーツについて書いていきます。
間違いがありましたらご指摘いただけると幸いです。

### PKCanvasView

Apple Pencilでの書き込みを受け付けるViewです。
UIScrollViewを継承しており、ContentSizeを拡大することでスクロールなども行うことができます。

### PKDrawing

Apple Pencilによる書き込みデータです。
Codableを継承しているので、エンコードしてファイルとして保存することもできます。

### PKToolPicker

ペンの色を選択したり、消しゴムを選択したりするペンツールセットです。
viewではなくwindowに対して紐付けして使用します。

<img width="468" alt="スクリーンショット 2019-10-09 22.15.07.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428744/1fc0d11a-82a5-102d-c1e6-25686e2b2a6d.png">


## PencilKit周りのいろいろ

```swift
var canvasView: PKCanvasView!
var toolPicker : PKToolPicker?
```

### PKCanvasViewの初期化

指での書き込みを無効化

```swift
canvasView.allowsFingerDrawing = false
```

背景の透明化

```swift
canvasView.isOpaque = false
```

### PKToolPickerの表示

AppleのDocumentationにあるExampleが大変参考になりました。
https://developer.apple.com/documentation/pencilkit/drawing_with_pencilkit

```swift
override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    if let window = parent?.view.window, let toolPicker = PKToolPicker.shared(for: window) {
        self.toolPicker = toolPicker
        self.toolPicker!.setVisible(true, forFirstResponder: canvasView)
        self.toolPicker!.addObserver(canvasView)
        self.toolPicker!.addObserver(self)
        canvasView.becomeFirstResponder()
    }
    parent?.view.window?.windowScene?.screenshotService?.delegate = self
}
```

ツールの表示・非表示の切り替えは`setVisible()`で行うことができます。

```swift
func togglePickerTool(_ visible : Bool){
    if toolPicker != nil {
        toolPicker!.setVisible(visible, forFirstResponder: canvasView)
    }
}
```

## PKDrawingの保存

PKDrawing単体で管理するのは大変なので、IDなどと一緒に保存します。
保存するデータのひとまとまりを次のクラスで定義します。

```swift
public class Note : Codable {
    public var drawing: PKDrawing
    public var uuid = UUID()
    // その他タイトルや最終更新日など必要なものを定義
}
```

ファイルへの保存

```swift
let note = Note(drawing: canvasView.drawing)
let localDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let url = localDirectory.appendingPathComponent("\(note.uuid).custom")

let encoder = PropertyListEncoder()

do {
    let data = try encoder.encode(note)
    try data.write(to: url)
    print("successfully saved item \(note.uuid)")
} catch {
    os_log("Could not save data model: %s", type: .error, error.localizedDescription)
}
```

ファイルの読み込み

```swift
var loadedNote: Note

let decoder = PropertyListDecoder()

do {
    let data = try Data(contentsOf: url)
    loadedNote = try decoder.decode(Note.self, from: data)
} catch {
    os_log("Could not load data model: %s", type: .error, error.localizedDescription)
}
```

# おわりに
今回簡単にApple Pencilを用いたアプリが開発できるようになったので、PencilKitとWKWebViewを組み合わせたアプリケーションを作成しました。

個人的にはQiitaやMedium等の記事に色々思ったことを書き込んでいく、、、ということを想定して作っています。

よろしければぜひ使ってみてください。

[<img width = 120 src = "https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428744/a349c00d-e333-44f8-3cda-ab9227d004fb.png">](https://apps.apple.com/us/app/notewind/id1482532727) Notewind