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

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

ainame
September 17, 2021

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

ainame

September 17, 2021
Tweet

More Decks by ainame

Other Decks in Technology

Transcript

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

    View full-size slide

  2. 自己紹介
    生井智司/ Satoshi Namai / @ainame
    ● Senior iOS Engineer at Cookpad Ltd
    ● イギリス地方都市ブリストル在住
    ● 今年からfastlane core contributor
    ○ Ruby 3 対応
    ○ deliverの高速化・改善など...

    View full-size slide

  3. レシピサービス クックパッドの海外展開

    View full-size slide

  4. 海外版Cookpad iOSアプリ
    ● 日本国内版とは別のコードベース/Bundle ID
    ● 日本のストア以外へ公開
    ● アプリ内言語で30言語対応 (日本語除く)
    ● App Store上のメタデータは22言語対応(同上)
    * 2021年8月末現在

    View full-size slide

  5. 発表内容
    ● App Store スクリーンショットとは
    ● i18nでの運用について
    ● App Storeスクリーンショットの自動生成
    ● 既存ツールの課題
    ● SwiftUIでスクリーンショット自動生成
    ○ SwiftUIを用いた画像の生成
    ○ TestPlanを用いたUIテスト
    ○ CLI化〜運用

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  8. App Store スクリーンショットとは
    ● アプリの体験を視覚的に伝える手段
    ● 各言語の画面サイズ毎に各10枚まで
    ● アプリの申請の際の審査の対象
    ● 対応デバイスごとに以下の画面サイズ向けの物が必要
    ○ iPhone - 6.5inch, 5.5inch
    ○ iPad - iPad Pro 12.9 inchの2nd genと4th gen

    View full-size slide

  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/

    View full-size slide

  10. App Store スクリーンショットとは
    発表ではテキスト/背景画像/アプリ画面
    を組み合わせたパターンを解説
    またスクリーンショット => スクショと略して、
    App Store スクショ、アプリ画面スクショのように表記する

    View full-size slide

  11. i18nでの運用について
    ● i18n = internationalization (国際化)
    ● 以下の対応が必要となる
    ○ アプリ内のテキストの翻訳
    ○ App Storeスクショ上のテキストの翻訳
    ○ アプリ画面スクショ用のアプリ内コンテンツの準備
    アプリの翻訳だけでなくApp Storeスクショ専用の
    翻訳/ローカライズの準備が必要

    View full-size slide

  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)分

    View full-size slide

  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月現在)
    頻繁な更新が必要になると人々のリソースを圧迫

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  17. i18nでの運用について(弊社での問題2)
    一部の地域でデザインを完全外注したが、担当者のApp Store
    スクショに関する知識・経験がなく手戻りが発生
    ● 画像が仕様に沿ってない(解像度、alphaチャンネルなど)
    ● 拡張子と画像フォーマットが不一致 (xxx.jpgだけど中身がpngなど)
    ● ステータスバーが中途半端(バッテリーが赤、キャリア名が残るなど)
    ● そもそもAndroid版の画面を使われる
    自前のガイドラインを準備はしたがそれでも難しい

    View full-size slide

  18. i18nでの運用について(まとめ)
    ● App Storeスクショ用の翻訳・コンテンツの準備が必要
    ● 頻繁な更新が必要になると人々のリソースを圧迫
    ● 多言語のアプリ画面のスクショを人手で集めるのが難しい
    ● 外注も大変
    弊社では自動化への機運が高まった

    View full-size slide

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

    View full-size slide

  20. App Storeスクリーンショットの自動生成
    snapshot - ローカライズされたアプリのスクショをUIテストで撮
    影して集めることが出来るテストランナー
    ● 並列実行をサポートしたりリトライも出来る
    ● ローディング中の撮影を回避出来るヘルパー
    ● ステータスバーの上書き (9:41の表示など)

    View full-size slide

  21. https://docs.fastlane.tools/actions/snapshot/

    View full-size slide

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

    View full-size slide

  23. https://docs.fastlane.tools/actions/frameit/

    View full-size slide

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

    View full-size slide

  25. 既存ツールの課題 (snapshot)
    snapshot/frameitを試したが実運用するための課題が散見される
    ● 言語数が多いと遅すぎる
    ○ 言語毎にシュミレーター向けの設定をしていて時間がかかってる
    ○ 4コアCPUだと3並列でしか実行できない (cpuコア数 - 1の並列数が設定される)
    ● 依存している技術が古いままなため現代のアプリの挙動に対応しきれていない
    ○ スクショを撮るタイミングを調整するために
    iOS13で廃止されたNetwork activity
    indicatorの監視処理を利用している
    ● リトライしても失敗し続ける場合、後にどこで失敗したかわからないので
    一部の言語・環境特有のエラーが再現し続けた時にデバッグしづらい

    View full-size slide

  26. 既存ツールの課題 (frameit)
    snapshot/frameitを試したが実運用するための課題が散見される
    ● 画像の出力に利用されているImageMagick単体では
    アラビア文字の反転・リガチャー処理が対応できない

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  31. 既存ツールの課題(まとめ)
    ● frameitでは弊社の要求を満たせなかった
    ● snapshotも痒いところに手が届かない
    でも自動化はしたい=> それぞれの代替を実装した
    難しそうなframeitから考える

    View full-size slide

  32. イメージ図
    snapshot -> 何か1 frameit -> 何か2
    https://developer.apple.com/design/human-interface-guidelines/macos/icons-and-images/app-icon/
    ImageMagickより
    高級な何か...
    試行錯誤しやすい
    テストランナー...

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  42. SwiftUIでスクショ自動生成
    フレーム画像をpng化しNSImageとして全体のViewと合成

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  46. SwiftUIでスクショ自動生成
    SwiftUIをレンダリングエンジンとして利用するメリット
    ● アプリ開発と同じ感覚で作れるのでi18n対応しやすい
    ○ LTR/RTL、text wrapping、画像のリサイズ・合成何でも出来る
    ○ デフォでSystemフォントが使われ準備要らず
    ● 1つのViewで全スクリーンサイズ対応も可能
    ● Previewを活用すればデバッグしやすい
    ● DSLなので可読性も高くてメンテしやすい

    View full-size slide

  47. SwiftUIでスクショ自動生成
    ainame/FrameKit
    App StoreスクショをSwiftUIのViewから生成するライブラリ
    ● SPMでインストールする
    ● ViewやLayoutの設定はSwiftで自分で定義
    ● $ fastlane frameit download_frames のフレーム画像を再利用
    ● 与えたデータに基づいてアプリ画面スクショのはめ込みと
    画像の合成をやってくれる

    View full-size slide

  48. AppStoreScreenshotView protocol

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  51. 固定フォントサイズ

    View full-size slide

  52. 先ほど定義したViewとLayout設定

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  55. SwiftUIでスクショ自動生成
    どうせだからsnapshot相当の再実装も自前でやってみる
    Xcode 11から導入されたTest Plan + xcresult を利用
    ● Test Plan - テスト条件をxctestplanファイルで一括管理
    ○ 環境変数で言語ごとのアカウント情報などの管理が実現
    ○ 特定のテスト条件を有効・無効が指定できる
    ● xcresult - XCTestのテスト結果、添付ファイルをまとめてくれる
    ○ xcresulltoolというCLIでデータを取得出来る
    ○ スクショを添付できる
    ○ どこでテストが失敗したかログが残る
    ○ 実行ごとの履歴が残るので便利

    View full-size slide

  56. SwiftUIでスクショ自動生成
    実装すべき機能/要件
    ● iOSシュミレーターの準備
    ○ 物理キーボードの無効化とステータスバーのオーバーライド
    ○ シュミレーターの事前起動
    ● xctestplanの更新
    ○ CLIで指定した言語のテスト条件のみを有効にする
    ● xcodebuildによるテスト実行
    ○ CLIで指定したデバイスのみをdestinationに追加する
    ○ 再実行する際にbuildをskip出来るようにする
    ● xcresultからスクリーンショットの抽出

    View full-size slide

  57. SwiftUIでスクショ自動生成
    iOSシュミレーターの準備

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  62. SwiftUIでスクショ自動生成
    xctestplanの更新
    ● 中身がJSONなのでテスト条件は
    Encodableなモデルで生成可能
    ● コマンドラインオプションに
    応じて値を動的に変える
    ● CLIから一部のロケールのみの
    テストを実行するために利用
    有効・無効の切り替え

    View full-size slide

  63. SwiftUIでスクショ自動生成
    xcodebuildによるテスト実行
    ● -resultBundlePathで.xcresultファイルの出力先を指定
    ● -destinationで先ほど作ったシュミレーターを指定

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  67. YouTube Demo動画

    View full-size slide

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

    View full-size slide

  69. SwiftUIでスクショ自動生成
    実際に運用してみた
    1. デザイナーとApp Storeスクショのデザインをすり合わせ
    2. SwiftUIでApp Storeスクショのレイアウトを実装
    3. 翻訳管理ツール上でスクショ内のテキストの翻訳を
    各地のコミュニティーマネージャーに依頼
    4. 自作ツールの実行
    5. 完成したスクショを各コミュニティーマネージャーに確認
    6. fastlane/deliverでApp Storeへ反映

    View full-size slide

  70. SwiftUIでスクショ自動生成
    Pros
    ● 2年弱更新してなかった状態から2、3ヶ月に1度の更新に!
    ● 一度デザイン・翻訳などが決まればあとはスクリプトを実行するだけでス
    クショの更新が可能で楽
    ● 生成した画像のフォーマットは必ず仕様通りなので手戻り無し
    Cons
    ● アプリUIの変更ごとにUIテストも追従していくのはそこそこ大変
    ● 各種設定値までSwiftで書いているのでCLIツールそのもののコンパイ
    ルが修正ごとに必要になっていてポータビリティが低すぎる

    View full-size slide

  71. Make everyday cooking fun!
    ご静聴ありがとうございました

    View full-size slide

  72. 想定Q&A
    Q: CIで実行しないのか
    A: 難しそう(翻訳依存でUIテストが落ちることがある)+ 毎リ
    リース更新のニーズはないのでやってない
    Q: 実行時間どれぐらい?
    A: MacBook Pro 2019 16-inch (2.4 Ghz - 8 cores)で40分ぐら
    いで20言語分終わるけどUIテストの実行内容依存
    (APIのスタブを作るためUIテストを2回走らせてる)

    View full-size slide

  73. 想定Q&A
    Q: 表示コンテンツどうしているの?
    A: APIのスタブを用いて表示されるコンテンツは権利上OKなも
    のだけを表示するようにしてる
    Q: UIテストは不安定じゃない?
    A: UIテスト専任のエンジニアが頑張ってくれてある程度安定的
    に書けている。UIテストの不安定さ以上に言語毎の環境差によ
    るエラーが多い。

    View full-size slide

  74. OSS化について
    ● 公開する気持ちがある
    ● ただしfastlaneのpluginとしてRubyで再実装中
    ○ 公開済みのainame/FrameKitはframeitのように単独では利用不
    可なので何らかのラッパーとなるツールが必要
    ○ fastlane-community/xcresultでRubyでスクショを抽出できるよう
    になる見込み
    興味がある方は @ainame までご一報ください

    View full-size slide