$30 off During Our Annual Pro Sale. View Details »

Effective PencilKit / 新聞スクラップ体験の実現

Go Takagi
September 12, 2022

Effective PencilKit / 新聞スクラップ体験の実現

iOSDC2022 Day 2 Track B 13:00〜
Effective PencilKit / 新聞スクラップ体験の実現

WWDC 2019 で発表された PencilKit を利用することで、数行のコードで 標準メモアプリと同様の手描き体験をアプリに導入できます。

発表に先立ち、日本経済新聞社の紙面ビューアーアプリでは、Apple Pencil を用いた紙面画像にメモやハイライトを書き込める機能をリリースしました。

アプリの機能要件を満たすための独自拡張の実現には、様々な制約が立ちはだかりました。
たとえば、キャンバスに画像を載せる、ズームやスクロールなどビューアーとしての操作は残しつつ書き込みを一時的に無効にするなど、一見すると単純そうですが一筋縄ではいきません。

本セッションでは PencilKit の開発ノウハウを、ドキュメントと内部の動きから洞察した知見の両面から解説します。開発経験を踏まえ、紙の新聞に書き込みを行うユーザー体験をどのようにアプリへ落とし込んでいったか説明できればと思います。

Go Takagi

September 12, 2022
Tweet

More Decks by Go Takagi

Other Decks in Technology

Transcript

  1. E
    ff
    ective PencilKit


    新聞スクラップ体験の実現
    Go Takagi
    20
    22
    /
    09
    /
    12
    iOSDC JAPAN
    2 022
    Day
    2
    #Track B
    13
    :
    0 0

    View Slide

  2. Me ( Go Takagi )
    ‣ID


    • shimastripe / shimastriper


    ‣Work


    • 株式会社 ⽇本経済新聞社


    ‣ iOS 紙⾯ビューアーアプリ の開発を担当


    • iOSDC NOC チーム


    ‣Like


    • 柴⽝が⼤好きです!
    2
    2年ぶりにカムバックです!

    View Slide

  3. Keynote
    ‣PencilKit を拡張する


    • Example より更に先のユースケースへ対応


    ‣Points


    • PencilKit で Preview / Edit できる画⾯


    • 独⾃のペンツールを統合


    • テキストハイライト機能


    • ツールパレット


    • Test‧その他Tips
    3

    View Slide

  4. Introduction

    View Slide

  5. 紙⾯ビューアー: 新聞紙⾯画像に特化
    ‣紙⾯画像形式で読める


    • 縦 (+ 横) 書き 両対応


    • iPad 利⽤者多い


    • オフライン動作


    • Wi-Fi で夜間に⾃動DL


    • iOSDC
    2 0
    2 0
    もぜひ 🙏
    5
    AppStore ページより

    View Slide

  6. 紙⾯画像に描き込みを⾏いたい!
    6
    Zoom や Scroll ができる

    View Slide

  7. 紙⾯画像への描き込み => スクラップ体験
    ‣デジタルでも実現したい


    • 紙に描いて残す体験を再現


    ‣App単体では実現できなかった


    • Evernote export 越しのみ


    • (現在はこの機能は終了)
    7
    https://prtimes.jp/main/html/rd/p/
    0 0
    00 0
    0
    01
    9
    .
    0
    00
    0
    1 1
    11
    5
    .html

    View Slide

  8. Apple Pencil で描けるメモ機能をリリース
    8
    https://www.youtube.com/watch?v=JwltoOq_JeU

    View Slide

  9. Apple Pencil を⽤いた⾃由描画
    9
    ‣iPhone は指で描画可能

    View Slide

  10. 描いたメモは保存(ロック)し、表⽰+⾮表⽰できる
    ‣編集モードが切り替えできる


    • Preview / Edit


    • Preview 中は Scroll / Zoom のみ可能


    ‣描き込み表⽰が切り替えできる


    • 描き込み ON / OFF


    ‣保存したデータはSyncされる


    • 端末をまたいで描き込みメモが残せる
    1
    0

    View Slide

  11. 段落も考慮した本⽂のハイライトマーカー
    ‣独⾃ペンツールを統合


    • HighlightKit を内製


    • Canvas に共存して利⽤可能に
    1
    1

    View Slide

  12. PencilKit でどうやるの...?
    ‣本セッション: PencilKit の拡張⽅法を学んでいきます


    • PencilKit のユースケースを広げる拡張を紹介!


    ‣deploymentTarget


    • iOS
    1
    4
    +


    • iPadOS
    1 4
    +
    1
    2

    View Slide

  13. PencilKit

    View Slide

  14. WWDC:
    19
    登場
    ‣3⾏のコードで Apple Pencil 描き込み体験を実現


    • キャンバスの作成


    • ビュー階層の追加


    • Ink の選択


    ‣iPad だけでなく iPhone も可能


    • 指で描き込み
    1
    4
    let canvas = PKCanvasView(frame: view.frame)


    view.addSubview(canvas)


    canvas.tool = PKInkingTool(.pen, color: .black, width: 30)

    View Slide

  15. Apple Pencil
    ‣低レイテンシ


    • 1秒間に240回スキャニングして情報を送る (240 Hz)


    • 描いたイメージとディスプレイへの描画遅れが極⼩


    ‣たくさんの情報


    • altitude (⾼度) / pressure (圧⼒) / azimuth (⽅位)


    ‣Scribble による⼿書き認識 (iOS
    1 4
    +)


    • タブレットの⼊⼒⽅法に新しい体験
    1
    5

    View Slide

  16. PencilKit のここが凄い!
    ‣Apple Pencil 体験を容易に導⼊できる


    • OS 標準の Canvas が再現できる


    ‣低レイテンシ


    • Pencil から送られる⼊⼒を素早く画⾯に反映


    • Metal の API を⽤いたレンダリング


    ‣描画したものが構造的なデータで表されている


    • 永続化して再編集可能


    ‣Image形式で出⼒可能


    • サムネイル画像が⽣成できる
    1
    6
    WWDC:
    1 9
    Introducing PencilKit

    View Slide

  17. 独⾃実装する場合 (≠ PencilKit )
    ‣UIKit のタッチイベントは 60 Hz


    • 精度⾼く滑らかに描画するために、2種類のデータをハンドリングする


    • 予測値を受けとって爆速描画‧遅れて来る実測値を更新反映 (補正)


    • ⼀筋縄ではいかない!PencilKit とても便利
    1
    7
    https://developer.apple.com/documentation/uikit/pencil_interactions/handling_input_from_apple_pencil


    https://developer.apple.com/documentation/uikit/touches_presses_and_gestures/handling_touches_in_your_view/getting_high-
    fi
    delity_input_with_coalesced_touches

    View Slide

  18. Example App: Drawing with PencilKit
    ‣⼀通りまとまってる


    • Canvas を表⽰する


    • 描き込み領域の⾃動拡張⽅法


    • ペンのツールパレットを表⽰する


    • Undo / Redo


    • 署名 (Signature)


    • サムネイル⽣成


    • PKDrawing (描き込みデータ) の永続化
    1
    8
    https://developer.apple.com/documentation/pencilkit/drawing_with_pencilkit
    ⼀通りアプリが作れそう!

    View Slide

  19. Example 以上のことできなくない......?🤔
    ‣⼀通りリッチに機能はあるけど


    • Example 以上のものを作れない


    • 絶妙にやりたいことに⼿が届かない
    1
    9
    と思ったのは⾃分だけじゃない......はず??

    View Slide

  20. もっともっと拡張したい
    ‣PencilKit の Drawing 体験を拡張したい


    • 画像に対して描き込み


    • 保存して描き込みを無効化


    • 描き込みの表⽰‧⾮表⽰切り替え


    ‣独⾃実装したペンツールを統合したい


    • 本⽂ハイライトマーカー


    ‣ツールパレットのカスタマイズ


    • ToolPickerをカスタマイズしたい
    2
    0

    View Slide

  21. できる拡張を探して実現していく
    ‣View の構造に着⽬


    • PencilKit の性質から構造を推測


    • 可能そうな拡張⽅法を試していく


    ‣PencilKit の資産を活かしてアプリが作れる


    • ユースケースを満たしつつ、再実装を避ける
    2
    1

    View Slide

  22. Example を通して PencilKit を紹介

    View Slide

  23. ⼤まかな構成
    ‣PKCanvasView


    • キャンバスとなる UIScrollView


    ‣PKToolPicker


    • ペンツール (ペン‧鉛筆‧消しゴム‧定規)


    • PKTool: PKInkingTool / PKEraserTool / PKLassoTool


    ‣PKDrawing


    • 描き込みデータを表す構造体‧ストロークのパスも取れる


    • Codable に対応、永続化‧復元が容易にできる


    • UIImage への変換も可能


    2
    3
    https://developer.apple.com/documentation/pencilkit/drawing_with_pencilkit

    View Slide

  24. 拾えるイベント
    ‣PKCanvasViewDelegate


    • UIScrollViewDelegate


    • PKDrawing 周りの変更イベント


    • Tool を使って描き始め / 終わり


    ‣PKToolPickerObserver


    • ToolPicker の選択 / 移動 / 表⽰
    2
    4
    ダークモードだと⾊が反転
    https://developer.apple.com/documentation/pencilkit/drawing_with_pencilkit

    View Slide

  25. Example から学べること
    ‣⼀連の描き込み体験は作れる


    • 描き込みキャンバスの実現


    • Drawing の変更時に Undo / Redo を適宜更新


    • 余⽩が狭くなったらキャンバスサイズの更新


    • リアルタイムで更新して無限キャンバスも


    • Canvas をカスタマイズする要素は⾒当たらない


    • Canvasにイメージを⼊れる⽅法はわからない......


    ‣永続化‧画像化


    • PKDrawing を Data に変換して保存


    • UIImage を書き出して保存
    2
    5

    View Slide

  26. 拡張に取り組んでいく

    View Slide

  27. もっともっと拡張したい
    ‣PencilKit の Drawing 体験を拡張したい


    • 画像に対して描き込み


    • 保存して描き込みを無効化


    • 描き込みの表⽰‧⾮表⽰切り替え


    ‣独⾃実装したペンツールを統合したい


    • 本⽂ハイライトマーカー


    ‣ツールパレットのカスタマイズ


    • ToolPickerをカスタマイズしたい
    2
    7

    View Slide

  28. 画像へ描き込みを実現したい

    View Slide

  29. UIImageView in UIScrollView
    ‣⼤きいコンテンツを部分的に表⽰するカメラ(View)


    • ContentView: ScrollView の subview


    • Zoomやスクロール、余⽩をカスタマイズできる
    2
    9
    https://developer.apple.com/library/archive/documentation/WindowsViews/Conceptual/UIScrollView_pg/Introduction/Introduction.html

    View Slide

  30. 既存紙⾯画像ページ: ⼀般的なImageViewer
    ‣UIScrollView の中に Image


    • ズーム‧スクロールができる


    • 画像は3段階の画質をサポート


    ‣カスタマイズ


    • ダブルタップでカスタムジェスチャー


    • 横書きモードの表⽰‧保存‧共有


    • iPad SplitView
    3
    0
    UIScrollView

    View Slide

  31. ImageViewer に描き込みを⾏いたい
    ‣ImageViewer に PKCanvasView ( UIScrollView ) を重ねる


    • 重ねて同時に操作してみる?
    3
    1
    UIScrollView
    PKCanvasView

    View Slide

  32. 失敗......というか断念

    View Slide

  33. 2枚の同期が難しい
    ‣Zoom の調整


    • ContentView 同⼠のサイズが違うと、 Zoom する⼤きさや位置が変わる


    • iPhone, iPad, SplitView でも対応しないといけない


    ‣PencilKit 側の描画が遅れる


    • 別の View 越しにイベントを伝えているため?


    • ⽬で⾒てアウトな品質に


    ‣何より管理が複雑


    • 機能追加するたびに UIScrollView が増えたりしたら......⽅針を変える
    3
    3

    View Slide

  34. PKCanvasView = UIScrollView
    ‣UIScrollView として観察してみる


    • ContentView = 描き込み領域?


    • 発⾒できれば


    • ContentView に Image を Insert できないか


    • 実現できれば ScrollView
    1
    枚化ができそう
    3
    4
    https://developer.apple.com/documentation/pencilkit/drawing_with_pencilkit

    View Slide

  35. Debug Hierarchy で覗いてみる
    ‣PKCanvasView の subviews には


    • UIView ( ContentView っぽい)


    • subviews に PKCanvasAttachmentView


    • PKTiledCanvasView (hidden)


    • PKTiledView


    • PKSelectionGestureView


    • _UIScrollViewScrollIndicator *
    2

    • スクロールインジケーター
    3
    5

    View Slide

  36. Debug Hierarchy で覗いてみる
    ‣PKCanvasView の subviews には


    • UIView ( ContentView っぽい)


    • subviews に PKCanvasAttachmentView


    • PKTiledCanvasView (hidden)


    • PKTiledView


    • PKSelectionGestureView


    • _UIScrollViewScrollIndicator *
    2

    • スクロールインジケーター
    3
    6

    View Slide

  37. (参考までに) UIScrollView の場合は
    ‣構造が似ている


    • UIImageView ( ContentView )


    • _UIScrollViewScrollIndicator *
    2

    • スクロールインジケーター
    3
    7

    View Slide

  38. ContentView? に View を⼊れてみる
    ‣PKCanvasView


    • backgroundColor = .systemRed


    ‣UIImageView を⼊れてみる


    • ContentView に Insert
    3
    8

    View Slide

  39. Drawing 中 背景⾊になってしまう
    ‣PKCanvasView


    • PKCanvasAttachment の tintColor と連携?


    • backgroundColor = .clear にしてみると.......


    ‣UIImageView と 背景 UIView


    • ContentView に Insert


    • 必要あれば背景 View を追加で Insert
    3
    9

    View Slide

  40. 画像の上に描き込みができる!
    ‣ScrollやZoomも滑らか!ズレない!


    • 描き込み領域は


    • canvasView.contentSize を設定して調整可能


    • ImageSize から必要な余⽩を計算し、contentSize にする


    ‣3種類の画質の画像と合成


    • PKDrawing と画像を分けて保存


    • 画像サイズに応じて倍率を計算し、Drawingと重ねる
    4
    0

    View Slide

  41. (再掲) 既存紙⾯画像ページ: ⼀般的なImageViewer
    ‣UIScrollView の中に Image


    • ズーム‧スクロールができる


    • 画像は3段階の画質をサポート


    ‣カスタマイズ


    • ダブルタップでカスタムジェスチャー


    • 横書きモードの表⽰‧保存‧共有


    • iPad SplitView
    4
    1
    UIScrollView

    View Slide

  42. PKCanvasView で UIScrollView + α (移植)!
    ‣PKCanvasView の中に Image


    • ズーム‧スクロールができる


    • 画像は3段階の画質をサポート


    ‣カスタマイズ (移植)


    • ダブルタップでカスタムジェスチャー


    • 横書きモードの表⽰‧保存‧共有


    • iPad SplitView
    4
    2
    PKCanvasView

    View Slide

  43. 4
    3
    PencilKit!
    UIScrollView PKCanvasView

    View Slide

  44. もっともっと拡張したい
    ‣PencilKit の Drawing 体験を拡張したい


    • 画像に対して描き込み


    • 保存して描き込みを無効化


    • 描き込みの表⽰‧⾮表⽰切り替え


    ‣独⾃実装したペンツールを統合したい


    • 本⽂ハイライトマーカー


    ‣ツールパレットのカスタマイズ


    • ToolPickerをカスタマイズしたい
    4
    4

    View Slide

  45. もっともっと拡張したい
    ‣PencilKit の Drawing 体験を拡張したい


    • 画像に対して描き込み


    • 保存して描き込みを無効化


    • 描き込みの表⽰‧⾮表⽰切り替え


    ‣独⾃実装したペンツールを統合したい


    • 本⽂ハイライトマーカー


    ‣ツールパレットのカスタマイズ


    • ToolPickerをカスタマイズしたい
    4
    5

    View Slide

  46. Preview / Edit の切り替え

    View Slide

  47. Canvas を Preview / Edit 切り替えする
    ‣メモアプリ


    • Preview は1本指でスクロール


    • Edit は、1本指で描画、2本でスクロール


    ‣描き込みだけ OFF にするには


    canvasView.isUserInteractionEnabled = false


    • 全ての Gesture が動かなくなる.......


    canvasView.drawingGestureRecognizer.isEnabled


    • Drawing に関する操作だけ Disabled にできる
    4
    7
    Preview Edit


    View Slide

  48. 4
    8
    PencilKit!
    UIScrollView PKCanvasView

    View Slide

  49. 4
    9
    Draw ON
    Draw OFF
    Pencil で描ける!
    スクロール操作のみできる
    Edit
    Preview
    UIScrollView
    PKCanvasView の描き込みモードを切り替える

    View Slide

  50. 5
    0
    Pencil で描ける!
    スクロール操作のみできる
    ダブルタップや保存‧共有機能を移植する!
    Edit
    Preview
    Draw ON
    Draw OFF

    View Slide

  51. 描き込み内容の⼀時⾮表⽰
    ‣PKCanvasAttachmentView の hidden で可能
    5
    1
    Hidden
    Appear

    View Slide

  52. もっともっと拡張したい
    ‣PencilKit の Drawing 体験を拡張したい


    • 画像に対して描き込み


    • 保存して描き込みを無効化


    • 描き込みの表⽰‧⾮表⽰切り替え


    ‣独⾃実装したペンツールを統合したい


    • 本⽂ハイライトマーカー


    ‣ツールパレットのカスタマイズ


    • ToolPickerをカスタマイズしたい
    5
    2

    View Slide

  53. もっともっと拡張したい
    ‣PencilKit の Drawing 体験を拡張したい


    • 画像に対して描き込み


    • 保存して描き込みを無効化


    • 描き込みの表⽰‧⾮表⽰切り替え


    ‣独⾃実装したペンツールを統合したい


    • 本⽂ハイライトマーカー


    ‣ツールパレットのカスタマイズ


    • ToolPickerをカスタマイズしたい
    5
    3

    View Slide

  54. 独⾃マーカーの実装
    ‣テキストハイライト


    • 本⽂に沿って


    • 滑らかに綺麗に
    5
    4
    PencilKitのマーカーでは


    滲んで⾒えてしまう

    View Slide

  55. HighlightKit を開発
    ‣滑らかなテキストマーカー


    • 1⽂字ごとの個別サイズに対応


    • 段落を考慮してハイライト


    ‣拡張機能をモジュールで⽤意


    • SPM Package で実現
    5
    5

    View Slide

  56. 独⾃マーカー⽤の View も ContentView に⼊れる
    ‣PKCanvasView を UIScrollView として更に使う!


    • ContentView


    • CanvasBackgroundView


    • ImageView


    • PKCanvasAttachmentView


    • HighlightView


    • PKTiledCanvasView (hidden)


    • ...etc.
    5
    6

    View Slide

  57. 独⾃マーカー⽤の View も ContentView に⼊れる
    ‣PKCanvasView を UIScrollView として更に使う!


    • ContentView


    • CanvasBackgroundView


    • ImageView


    • PKCanvasAttachmentView


    • HighlightView


    • PKTiledCanvasView (hidden)


    • ...etc.
    5
    7
    台紙となる背景
    紙⾯画像
    ⼿描き領域
    独⾃マーカー

    View Slide

  58. 5
    8
    Pencil で描ける!
    スクロール操作のみできる
    Edit
    Preview
    Draw ON
    Draw OFF
    Highlight
    Draw OFF
    Draw ON
    独⾃マーカー!

    View Slide

  59. Highlightの仕組み
    ‣始点と終点をキャプチャ


    • 間にある番号をすべて塗る
    5
    9


















































    View Slide

  60. ポインタが ① から ⑯ へいったら
    ‣始点と終点をキャプチャ


    • 間にある番号をすべて塗る
    6
    0


















































    View Slide

  61. ポインタが ㉖ から ㊳ へいったら
    ‣段落をまたいでもハイライトできる


    • データ側で順序を計算しておく
    6
    1


















































    View Slide

  62. 新聞画像のテキスト領域の抽出
    ‣既存の OCR の精度で限界


    • OCRとは画像から⽂字の領域と内容を抽出する技術のこと


    • 新聞特有の性質と相性が悪かった


    • 可変幅フォント


    • 組み⽂字


    • 段落順序がバラバラ


    • (直感的でない)


    • 技術的制約で⽂字埋め込みのPDFの使⽤は困難
    6
    2

    View Slide

  63. 新聞縦書き向け⽂字座標抽出ロジックを開発
    6
    3
    Google Cloud Vision API 開発した⼿法
    ※ 2022年04⽉時点

    View Slide

  64. もっともっと拡張したい
    ‣PencilKit の Drawing 体験を拡張したい


    • 画像に対して描き込み


    • 保存して描き込みを無効化


    • 描き込みの表⽰‧⾮表⽰切り替え


    ‣独⾃実装したペンツールを統合したい


    • 本⽂ハイライトマーカー


    ‣ツールパレットのカスタマイズ


    • ToolPickerをカスタマイズしたい
    6
    4

    View Slide

  65. もっともっと拡張したい
    ‣PencilKit の Drawing 体験を拡張したい


    • 画像に対して描き込み


    • 保存して描き込みを無効化


    • 描き込みの表⽰‧⾮表⽰切り替え


    ‣独⾃実装したペンツールを統合したい


    • 本⽂ハイライトマーカー


    ‣ツールパレットのカスタマイズ


    • ToolPickerをカスタマイズしたい
    6
    5

    View Slide

  66. PKToolPicker

    View Slide

  67. PKToolPicker
    ‣メモの Tool パレットを利⽤可能!


    • iPhone / iPad で機能差があることに注意


    • iPhone は「Undo‧Redo」がついていない


    • 3本指で左から右にスワイプすると同じジェスチャーがあります
    6
    7

    View Slide

  68. Phone モードでは個別に⽤意を検討
    ‣HIG で指摘されていました
    6
    8
    https://developer.apple.com/design/human-interface-guidelines/inputs/apple-pencil-and-scribble

    View Slide

  69. ほとんどカスタムできない
    ‣⼀部の設定の ON / OFF のみ


    • 定規を表⽰するか


    • 指で描画を許可する設定を出すかどうか


    ‣CustomTool の追加‧削除


    • できない、特定のTool だけ表⽰は無理
    6
    9
    マーカーだけ独⾃実装のものにしたいが...

    View Slide

  70. ToolPicker を完全に⾃作すればやれる.......
    ‣標準 ToolPicker を外から操作する


    • PKCanvasView.tool / PKToolPicker.selectedTool を上書き


    ‣独⾃ツールも⼊ったツールパレットを作りたい場合


    • 完全⾃作して UI を作る


    • 各種ボタンで Gesture をうまく切り替える


    • PKCanvasView の描き込み Gesture を ON/OFF


    • Custom Tool の Gesture を ON/OFF
    7
    0

    View Slide

  71. UISegmentControl 越しに切り替えてみる
    7
    1
    let control = UISegmentedControl(frame: .null, actions: [


    .init(title: "ϖϯ", handler: { _ in


    self.toolPicker.selectedTool = PKInkingTool(.pen)


    }),


    .init(title: "ϚʔΧʔ", handler: { _ in


    self.toolPicker.selectedTool = PKInkingTool(.marker)


    }),


    .init(title: "Ԗච", handler: { _ in


    self.toolPicker.selectedTool = PKInkingTool(.pencil)


    }),


    ])


    View Slide

  72. PKToolPicker のカスタマイズ情報
    ‣UserDefaults に保存


    • ユーザーが意図的に変えたか判断できる


    • 複数プリセットも⽤意可能


    • PKToolPicker の stateAutosaveName


    を上書きする
    7
    2

    View Slide

  73. もっともっと拡張したい
    ‣PencilKit の Drawing 体験を拡張したい


    • 画像に対して描き込み


    • 保存して描き込みを無効化


    • 描き込みの表⽰‧⾮表⽰切り替え


    ‣独⾃実装したペンツールを統合したい


    • 本⽂ハイライトマーカー


    ‣ツールパレットのカスタマイズ


    • ToolPickerをカスタマイズしたい
    7
    3

    View Slide

  74. Testing

    View Slide

  75. 拡張したPKCanvasViewをテストする
    ‣PKCanvasView の subviews の構造チェック


    • 想定と変わっていないことを確認


    • Private Class なので Test のみで厳密にチェックする
    7
    5
    let vc = ArticleCanvasViewController()


    vc.loadView()


    vc.viewDidLoad()


    // Private APIͳͷͰຊମίʔυʹೖΕͳ͍Α͏ʹ஫ҙ


    XCTAssertEqual(NSStringFromClass(type(of: vc.canvasView.subviews[0])), "UIView")


    XCTAssertEqual(NSStringFromClass(type(of: vc.canvasView.subviews[1])), "PKTiledCanvasView")


    XCTAssertEqual(NSStringFromClass(type(of: vc.canvasView.subviews[2])), "PKTiledView")


    XCTAssertEqual(NSStringFromClass(


    type(of: vc.canvasView.attachmentView)), "PKCanvasAttachmentView")


    View Slide

  76. 他にもカスタマイズした設定があれば Assert
    ‣ペンツールの設定


    • PKDrawing / PKToolPicker は Equatable に準拠


    • AssertionTest が書きやすい


    • 初期選択ツールのチェック


    • ユーザー選択後はそちらが維持されるチェック
    7
    6

    View Slide

  77. PKDrawingと画像の合成テスト
    ‣合成がズレていないかテストしたい


    • 描き込みデータを複数サイズの画像とマージ


    • 3段階の画質


    • iPhone / iPad の⾒た⽬
    7
    7
    3段階のサイズ


    と合体する

    View Slide

  78. ビジュアルリグレッションテスト
    ‣ 視覚の回帰テスト


    • View 単位でデグレを検知


    • スクリーンショットの Di
    ff
    を⽤いた差分検知 など


    • uber/ios-snapshot-test-case や pointfreeco/swift-snapshot-testing が有名
    7
    8
    A A'
    A'

    View Slide

  79. PKDrawing は Codable に対応
    ‣特定の描き込み状態を⽤意に再現可能


    • Data 型から復元して、Canvasに適⽤した画⾯を⽐較


    • 同じに⾒えて紙⾯画像は 3 種類別サイズ
    7
    9
    サイズ2000 サイズ3000 サイズ4000

    View Slide

  80. ただし CI は注意......
    ‣PKCanvasView は Metal でレンダリングする


    • Machine 環境に依って、レンダリングされないことがあった


    • スペックを上げることで正しく動くことがあった


    • 直接的な原因はまだ特定できてません
    8
    0
    https://developer.apple.com/jp/metal

    View Slide

  81. その他 Tips

    View Slide

  82. PKCanvasView は初回⽣成時重い
    ‣GPU (Metal) に依存しているため


    • タップしたタイミングで初回⽣成すると遅延が起きる


    • 事前に1度⽣成して⽴ち上げておく
    8
    2

    View Slide

  83. Pencil や指の特殊なショートカットを作りたい
    ‣UIGestureRecognizer で Interaction を区別可能


    • allowedTouchType で許可する


    ‣例えばペンシルでなぞる動作を拾うなら


    • allowedTouchType


    • [UITouch.TouchType.stylus]


    • minimumPressDuration / allowableMovement


    • ⼩さい値に / 広い値に
    8
    3
    https://developer.apple.com/documentation/uikit/uigesturerecognizer/
    1
    6 2
    4
    223
    -allowedtouchtypes

    View Slide

  84. Pencil
    2
    の Double-Tap (消しゴムと切り替え)
    ‣UIPencilInteraction


    • Delegate 関数でカスタマイズできる
    8
    4
    https://developer.apple.com/documentation/uikit/pencil_interactions/handling_double_taps_from_apple_pencil
    let pencilInteraction = UIPencilInteraction()


    pencilInteraction.delegate = self


    view.addInteraction(pencilInteraction)


    func pencilInteractionDidTap(_ interaction: UIPencilInteraction) {


    if UIPencilInteraction.preferredTapAction == .switchPrevious {


    leftRingControl.switchToPreviousTool()


    }


    }


    View Slide

  85. 画像に描き込む場合 Light に固定する (といい?)
    ‣画像に描きこむとダークモードは......


    • Drawingが黒と⽩で反転してしまう


    • Light モードを維持したい


    • systemColor は Light / Dark で少し違ったりも
    8
    5
    https://developer.apple.com/design/human-interface-guidelines/foundations/color

    View Slide

  86. Human Interface Guideline にも
    ‣コンテンツへの描き込みは⾊を固定しましょう


    • ⾊合いが変わってしまうため
    8
    6
    https://developer.apple.com/design/human-interface-guidelines/inputs/apple-pencil-and-scribble
    Help people draw on top of existing content. By default, the colors on your PencilKit
    canvas dynamically adjust to dark mode, so people can create content in either mode and
    the results will look great in both. However, when people draw on top of existing content
    like a PDF or a photo, you want to prevent the dynamic adjustment of colors so that the
    markup remains sharp and visible
    .

    PencilKit Custom Drawing - HIG -

    View Slide

  87. 具体的にどうするか?
    ‣UIUserInterfaceStyle を上書きする


    • PKCanvasView


    • overrideUserInterfaceStyle: UI の⾒た⽬


    • PKToolPicker


    • overrideUserInterfaceStyle: UI の⾒た⽬


    • colorUserInterfaceStyle: Drawing の選択⾊


    • 黒で描いた線が⽩になる
    8
    7
    外側だけ Dark も可能

    View Slide

  88. Tips 終わり!

    View Slide

  89. まとめ

    View Slide

  90. まとめ
    ‣PencilKit を拡張する


    • PencilKit の構造を UIScrollView の観点から観察


    • 画像や独⾃ Touch View を内部の View と⼲渉しないように合成する


    • PencilKit の編集モードを⽤意する


    • Preview‧Edit‧Highlight


    • リッチな機能を活かしつつ、追加拡張に成功


    • 快適なスクラップ体験の実現!
    9
    0

    View Slide