Upgrade to Pro — share decks privately, control downloads, hide ads and more …

iOSDC 2021 - App Store用スクリーンショットの自動生成をアラビア語対応してSwiftUIで実装してみた

45c0e67049c82c238143b82a1660a713?s=47 ainame
September 17, 2021

iOSDC 2021 - App Store用スクリーンショットの自動生成をアラビア語対応してSwiftUIで実装してみた

45c0e67049c82c238143b82a1660a713?s=128

ainame

September 17, 2021
Tweet

Transcript

  1. App Store用スクリーンショットの自動生成をアラ ビア語対応してSwiftUIで実装してみた 生井智司 / ainame

  2. 自己紹介 生井智司/ Satoshi Namai / @ainame • Senior iOS Engineer

    at Cookpad Ltd • イギリス地方都市ブリストル在住 • 今年からfastlane core contributor ◦ Ruby 3 対応 ◦ deliverの高速化・改善など...
  3. レシピサービス クックパッドの海外展開

  4. 海外版Cookpad iOSアプリ • 日本国内版とは別のコードベース/Bundle ID • 日本のストア以外へ公開 • アプリ内言語で30言語対応 (日本語除く)

    • App Store上のメタデータは22言語対応(同上) * 2021年8月末現在
  5. 発表内容 • App Store スクリーンショットとは • i18nでの運用について • App Storeスクリーンショットの自動生成

    • 既存ツールの課題 • SwiftUIでスクリーンショット自動生成 ◦ SwiftUIを用いた画像の生成 ◦ TestPlanを用いたUIテスト ◦ CLI化〜運用
  6. App Store スクリーンショットとは https://developer.apple.com/app-store/product-page/

  7. App Store スクリーンショットとは https://developer.apple.com/app-store/product-page/

  8. App Store スクリーンショットとは • アプリの体験を視覚的に伝える手段 • 各言語の画面サイズ毎に各10枚まで • アプリの申請の際の審査の対象 •

    対応デバイスごとに以下の画面サイズ向けの物が必要 ◦ iPhone - 6.5inch, 5.5inch ◦ iPad - iPad Pro 12.9 inchの2nd genと4th gen
  9. App Store スクリーンショットとは 2.3.3 Screenshots should show the app in

    use, and not merely the title art, login page, or splash screen. They may also include text and image overlays (e.g. to demonstrate input mechanisms, such as an animated touch point or Apple Pencil) and show extended functionality on device, such as Touch Bar. (意訳)スクリーンショットは使用中のアプリを見せべき。テキストや画 像のオーバーレイで、使い方を説明したりTouch Barなどのデバイス の機能の説明もしても良い https://developer.apple.com/app-store/review/guidelines/
  10. App Store スクリーンショットとは 発表ではテキスト/背景画像/アプリ画面 を組み合わせたパターンを解説 またスクリーンショット => スクショと略して、 App Store

    スクショ、アプリ画面スクショのように表記する
  11. i18nでの運用について • i18n = internationalization (国際化) • 以下の対応が必要となる ◦ アプリ内のテキストの翻訳

    ◦ App Storeスクショ上のテキストの翻訳 ◦ アプリ画面スクショ用のアプリ内コンテンツの準備 アプリの翻訳だけでなくApp Storeスクショ専用の 翻訳/ローカライズの準備が必要
  12. i18nでの運用について 運用上必要なスクリーンショットの枚数について考える ただしアプリはiPad対応済のユニバーサルアプリとする • (PM・デザイナー)App Storeスクショで訴求する機能を考えデザインに落とし込む ◦ 例:6枚分のデザインを考える • (誰か)アプリ画面スクショを収集

    ◦ 6レイアウト x 4デバイス分 ◦ iPhone 8 plus/12 Pro MaxとfiPad Pro 12.9 inch 2nd gen/4th gen • (デザイナー)各画面のスクショのはめ込み+テキスト+背景画像の作成 ◦ 6レイアウト x 4デバイス x 対応言語数(N)分
  13. i18nでの運用について 6レイアウト x 4デバイス x N言語 枚分の作成が必要 • N=1 ->

    24枚 • N=2 -> 48枚 • …… • N=22 -> 528枚 (弊社・2021年8月現在) • …… • N=39 -> 936枚(App Storeの対応言語数・2021年8月現在) 頻繁な更新が必要になると人々のリソースを圧迫
  14. i18nでの運用について(弊社での問題) アプリ内コンテンツのローカライズ => 言語・地域の知識がないと難しい

  15. i18nでの運用について(弊社での問題) アプリ内コンテンツのローカライズ => 言語・地域の知識がないと難しい

  16. i18nでの運用について(弊社での問題) アプリ内コンテンツのローカライズ => 言語・地域の知識がないと難しい 弊社では各地域のコミュニティーマネージャーに依頼していた。 しかし全ての地域で必要なiOSデバイスを持っているわけでは ない🥲 そもそもアプリ画面のスクショが集まらない問題

  17. i18nでの運用について(弊社での問題2) 一部の地域でデザインを完全外注したが、担当者のApp Store スクショに関する知識・経験がなく手戻りが発生 • 画像が仕様に沿ってない(解像度、alphaチャンネルなど) • 拡張子と画像フォーマットが不一致 (xxx.jpgだけど中身がpngなど) •

    ステータスバーが中途半端(バッテリーが赤、キャリア名が残るなど) • そもそもAndroid版の画面を使われる 自前のガイドラインを準備はしたがそれでも難しい
  18. i18nでの運用について(まとめ) • App Storeスクショ用の翻訳・コンテンツの準備が必要 • 頻繁な更新が必要になると人々のリソースを圧迫 • 多言語のアプリ画面のスクショを人手で集めるのが難しい • 外注も大変

    弊社では自動化への機運が高まった
  19. App Storeスクリーンショットの自動生成 自動化していくアプローチが複数存在 • UIテストでアプリ画面スクショを取る+画像の合成 ◦ fastlaneのsnapshot(screengrab)とframeitが人気 • 他にも撮影済みのアプリ画面スクショをはめこむだけのWebサイトや Sketch/Figmaプラグインなども

    => UIテスト+画像合成のパターンを紹介
  20. App Storeスクリーンショットの自動生成 snapshot - ローカライズされたアプリのスクショをUIテストで撮 影して集めることが出来るテストランナー • 並列実行をサポートしたりリトライも出来る • ローディング中の撮影を回避出来るヘルパー

    • ステータスバーの上書き (9:41の表示など)
  21. https://docs.fastlane.tools/actions/snapshot/

  22. App Storeスクリーンショットの自動生成 frameit - アプリ画面スクショをデバイスのフレームにはめ込む +テキスト+背景画像との合成が出来る • 前処理されたデバイスフレーム画像 • テキストの良い感じの配置・改行と

    フォントサイズの調整 • .stringsファイルによる翻訳
  23. https://docs.fastlane.tools/actions/frameit/

  24. イメージ図 snapshot frameit https://developer.apple.com/design/human-interface-guidelines/macos/icons-and-images/app-icon/

  25. 既存ツールの課題 (snapshot) snapshot/frameitを試したが実運用するための課題が散見される • 言語数が多いと遅すぎる ◦ 言語毎にシュミレーター向けの設定をしていて時間がかかってる ◦ 4コアCPUだと3並列でしか実行できない (cpuコア数

    - 1の並列数が設定される) • 依存している技術が古いままなため現代のアプリの挙動に対応しきれていない ◦ スクショを撮るタイミングを調整するために iOS13で廃止されたNetwork activity indicatorの監視処理を利用している • リトライしても失敗し続ける場合、後にどこで失敗したかわからないので 一部の言語・環境特有のエラーが再現し続けた時にデバッグしづらい
  26. 既存ツールの課題 (frameit) snapshot/frameitを試したが実運用するための課題が散見される • 画像の出力に利用されているImageMagick単体では アラビア文字の反転・リガチャー処理が対応できない

  27. https://github.com/mpcabd/python-arabic-reshaper 素朴にアラビア語のテキストを CLIに渡した場合: 左右が反転されていない =デー タ順に左から右へ表示 入力の文字を無理やり反転 した場合: リガチャー(合字)が考慮され ていない

    データを反転・リガチャー分の code pointを修正: 正しい表記 ImageMagickでアラビア語を画像として出力する例
  28. 既存ツールの課題 (frameit) snapshot/frameitを試したが実運用するための課題が散見される • 内部で画像の出力に利用されている ImageMagick単体では アラビア文字の反転・リガチャー (合字)処理が対応できない • 入力の文字列に応じてフォントサイズを自動で調整するが、

    翻訳テキストの長さが言語ごとに違いすぎて言語間で全く見た目が変わる (逆にフォントサイズを固定できない )
  29. 既存ツールの課題 (frameit) snapshot/frameitを試したが実運用するための課題が散見される • 内部で画像の出力に利用されている ImageMagick単体では アラビア文字の反転・リガチャー (合字)処理が対応できない • 入力の文字列に応じてフォントサイズを自動で調整するが、

    翻訳テキストの長さが言語ごとに違いすぎて言語間で全く見た目が変わる (逆にフォントサイズを固定できない )
  30. 既存ツールの課題 (frameit) snapshot/frameitを試したが実運用するための課題が散見される • 内部で画像の出力に利用されている ImageMagick単体では アラビア文字の反転・リガチャー (合字)処理が対応できない • 入力の文字列に応じてフォントサイズを自動で調整するが、

    翻訳テキストの長さが言語ごとに違いすぎて言語間で全く見た目が変わる (逆にフォントサイズを固定できない ) • 全言語を正しくレンダリングするためには全言語分のフォントが必要
  31. 既存ツールの課題(まとめ) • frameitでは弊社の要求を満たせなかった • snapshotも痒いところに手が届かない でも自動化はしたい=> それぞれの代替を実装した 難しそうなframeitから考える

  32. イメージ図 snapshot -> 何か1 frameit -> 何か2 https://developer.apple.com/design/human-interface-guidelines/macos/icons-and-images/app-icon/ ImageMagickより 高級な何か...

    試行錯誤しやすい テストランナー...
  33. SwiftUIでスクショ自動生成 UIKit/AppKitで画像を生成すれば良いのでは? • UIKitで普段アプリを作っていてアラビア語の表示は完璧 • UIGraphicsImageRendererなどでUIViewの画像化は簡単 • 実際にはCLIとしてmacOS上で実行したいのでAppKitを使ってみる • NSView.bitmapImageRepForCachingDisplayで画像化可能

  34. SwiftUIでスクショ自動生成 NSViewをPNGやJPEGなどのフォーマットに変換

  35. SwiftUIでスクショ自動生成 • AppKitとNSTextFieldとNSImageViewなどを 使えば画像生成いけそう • でも(UIKitエンジニアには)AppKitは難しい😭😭😭

  36. SwiftUIでスクショ自動生成 💡

  37. SwiftUIでスクショ自動生成

  38. SwiftUIでスクショ自動生成 SwiftUIならmacOSでもテキストの配置が簡単!

  39. ViewにlayoutDirectionをセットすることでRTLも対応可能 NSHostingView経由で画像化出来る SwiftUIでスクショ自動生成

  40. SwiftUIでスクショ自動生成 ViewにlayoutDirectionをセットすることでRTLも対応可能 NSHostingView経由で画像化出来る

  41. SwiftUIでスクショ自動生成 アプリ画面スクショのフレーム埋め込みもSwiftUI • fastlane/frameitの持つフレー ム画像を再利用 • ZStackで2枚の画像を重ねるだ けでピッタリ埋まる(デバイスが 左右対称なため) •

    iPad ProのみVolumeボタン分 のoffsetを調整
  42. SwiftUIでスクショ自動生成 フレーム画像をpng化しNSImageとして全体のViewと合成

  43. SwiftUIでスクショ自動生成 • 背景色・画像もZStackで重ねるだけで実現 • 複数枚のフレーム画像を重ねることも可

  44. SwiftUIでスクショ自動生成 • 背景色・画像もZStackで重ねるだけで実現 • 複数枚のフレーム画像を重ねることも可

  45. SwiftUIでスクショ自動生成 • 背景色・画像もZStackで重ねるだけで実現 • 複数枚のフレーム画像を重ねることも可 SwiftUIで実現できるレイアウトは何でも出来る!

  46. SwiftUIでスクショ自動生成 SwiftUIをレンダリングエンジンとして利用するメリット • アプリ開発と同じ感覚で作れるのでi18n対応しやすい ◦ LTR/RTL、text wrapping、画像のリサイズ・合成何でも出来る ◦ デフォでSystemフォントが使われ準備要らず •

    1つのViewで全スクリーンサイズ対応も可能 • Previewを活用すればデバッグしやすい • DSLなので可読性も高くてメンテしやすい
  47. SwiftUIでスクショ自動生成 ainame/FrameKit App StoreスクショをSwiftUIのViewから生成するライブラリ • SPMでインストールする • ViewやLayoutの設定はSwiftで自分で定義 • $

    fastlane frameit download_frames のフレーム画像を再利用 • 与えたデータに基づいてアプリ画面スクショのはめ込みと 画像の合成をやってくれる
  48. None
  49. AppStoreScreenshotView protocol

  50. 背景色 背景画像 フレーム済アプリ画面スクショ画像 テキスト * キーワード: 太文字で目立つやつ * タイトル: 短い機能の説明

  51. None
  52. pixel単位からmacOSで利用されるpointへ変換するヘルパー

  53. 固定フォントサイズ

  54. None
  55. 先ほど定義したViewとLayout設定

  56. 出力先のファイルパス

  57. SwiftUIでスクショ自動生成(まとめ1) • frameitで対応してないRTL言語のためにSwiftUIを利用 • SwiftUIで作ったViewは簡単に画像化出来るので、 画像生成のためのCLIツールへ利用可能 • ainame/FrameKitはSwiftUIを活用したライブラリ • アプリ開発の知識でスクショデザインを実装できる

  58. SwiftUIでスクショ自動生成 どうせだからsnapshot相当の再実装も自前でやってみる Xcode 11から導入されたTest Plan + xcresult を利用 • Test

    Plan - テスト条件をxctestplanファイルで一括管理 ◦ 環境変数で言語ごとのアカウント情報などの管理が実現 ◦ 特定のテスト条件を有効・無効が指定できる • xcresult - XCTestのテスト結果、添付ファイルをまとめてくれる ◦ xcresulltoolというCLIでデータを取得出来る ◦ スクショを添付できる ◦ どこでテストが失敗したかログが残る ◦ 実行ごとの履歴が残るので便利
  59. SwiftUIでスクショ自動生成 実装すべき機能/要件 • iOSシュミレーターの準備 ◦ 物理キーボードの無効化とステータスバーのオーバーライド ◦ シュミレーターの事前起動 • xctestplanの更新

    ◦ CLIで指定した言語のテスト条件のみを有効にする • xcodebuildによるテスト実行 ◦ CLIで指定したデバイスのみをdestinationに追加する ◦ 再実行する際にbuildをskip出来るようにする • xcresultからスクリーンショットの抽出
  60. SwiftUIでスクショ自動生成 iOSシュミレーターの準備

  61. xctestplanの更新 • 中身がJSONなのでテスト条件は Encodableなモデルで生成可能 • コマンドラインオプションに 応じて値を動的に変える SwiftUIでスクショ自動生成

  62. SwiftUIでスクショ自動生成 xctestplanの更新 • 中身がJSONなのでテスト条件は Encodableなモデルで生成可能 • コマンドラインオプションに 応じて値を動的に変える UUID

  63. SwiftUIでスクショ自動生成 xctestplanの更新 • 中身がJSONなのでテスト条件は Encodableなモデルで生成可能 • コマンドラインオプションに 応じて値を動的に変える 環境変数の設定

  64. SwiftUIでスクショ自動生成 xctestplanの更新 • 中身がJSONなのでテスト条件は Encodableなモデルで生成可能 • コマンドラインオプションに 応じて値を動的に変える 対象の言語・地域の設定

  65. SwiftUIでスクショ自動生成 xctestplanの更新 • 中身がJSONなのでテスト条件は Encodableなモデルで生成可能 • コマンドラインオプションに 応じて値を動的に変える • CLIから一部のロケールのみの

    テストを実行するために利用 有効・無効の切り替え
  66. SwiftUIでスクショ自動生成 xcodebuildによるテスト実行 • -resultBundlePathで.xcresultファイルの出力先を指定 • -destinationで先ほど作ったシュミレーターを指定

  67. SwiftUIでスクショ自動生成 xcodebuildによるテスト実行 • -resultBundlePathで.xcresultファイルの出力先を指定 • -destinationで先ほど作ったシュミレーターを指定 ◦ 複数指定すると並列に実行してくれる

  68. SwiftUIでスクショ自動生成 xcresultからスクリーンショットの抽出 • Swift製のCLI ChargePoint/xcparse をmint経由で インストールして利用

  69. SwiftUIでスクショ自動生成 紹介したコマンドなどを呼び出すCLIをSwiftで実装 • apple/swift-argument-parser コマンドのオプションの解析に利用 • ainame/FrameKit も内部で直接利用しているので 最終的には画像の生成まで行っている

  70. YouTube Demo動画

  71. SwiftUIでスクショ自動生成(まとめ2) • SPMプロジェクトとしてTestPlanとxcresultファイルを利用しsnapshot相 当のテストランナーとなるCLIツールを構築 • ほとんどの処理は外部のコマンドの呼び出しで完結 • TestPlan(.xctestplan)はJSONなので簡単にコードで制御出来る • UIテストの並列実行はデバイスごとの並列化はお手軽に出来る

  72. SwiftUIでスクショ自動生成 実際に運用してみた 1. デザイナーとApp Storeスクショのデザインをすり合わせ 2. SwiftUIでApp Storeスクショのレイアウトを実装 3. 翻訳管理ツール上でスクショ内のテキストの翻訳を

    各地のコミュニティーマネージャーに依頼 4. 自作ツールの実行 5. 完成したスクショを各コミュニティーマネージャーに確認 6. fastlane/deliverでApp Storeへ反映
  73. SwiftUIでスクショ自動生成 Pros • 2年弱更新してなかった状態から2、3ヶ月に1度の更新に! • 一度デザイン・翻訳などが決まればあとはスクリプトを実行するだけでス クショの更新が可能で楽 • 生成した画像のフォーマットは必ず仕様通りなので手戻り無し Cons

    • アプリUIの変更ごとにUIテストも追従していくのはそこそこ大変 • 各種設定値までSwiftで書いているのでCLIツールそのもののコンパイ ルが修正ごとに必要になっていてポータビリティが低すぎる
  74. Make everyday cooking fun! ご静聴ありがとうございました

  75. 想定Q&A Q: CIで実行しないのか A: 難しそう(翻訳依存でUIテストが落ちることがある)+ 毎リ リース更新のニーズはないのでやってない Q: 実行時間どれぐらい? A:

    MacBook Pro 2019 16-inch (2.4 Ghz - 8 cores)で40分ぐら いで20言語分終わるけどUIテストの実行内容依存 (APIのスタブを作るためUIテストを2回走らせてる)
  76. 想定Q&A Q: 表示コンテンツどうしているの? A: APIのスタブを用いて表示されるコンテンツは権利上OKなも のだけを表示するようにしてる Q: UIテストは不安定じゃない? A: UIテスト専任のエンジニアが頑張ってくれてある程度安定的

    に書けている。UIテストの不安定さ以上に言語毎の環境差によ るエラーが多い。
  77. OSS化について • 公開する気持ちがある • ただしfastlaneのpluginとしてRubyで再実装中 ◦ 公開済みのainame/FrameKitはframeitのように単独では利用不 可なので何らかのラッパーとなるツールが必要 ◦ fastlane-community/xcresultでRubyでスクショを抽出できるよう

    になる見込み 興味がある方は @ainame までご一報ください