Skip to content

feat: iOS版の「使い方」にバージョンを表示し、PNG・PDFの保存後にApp Storeの評価を依頼する - #121

Merged
K0mork merged 3 commits into
mainfrom
feat/version-and-review-request
Oct 7, 2026
Merged

K0mork merged 3 commits into
mainfrom
feat/version-and-review-request

Conversation

@K0mork

@K0mork K0mork commented Oct 6, 2026 •

Copy link
Copy Markdown
Owner

変更内容

  • バージョンの表示: iOS版の「使い方」の末尾(フッター)に「バージョン 1.0(ビルド 1)」の形でバージョンとビルド番号を表示します。SwiftがInfo.plistのCFBundleShortVersionString・CFBundleVersionを読み(ios/App/AppVersionInfo.swift)、WKUserScriptでwindow.knittingEditorAppInfoとして同梱ページへ渡します。通信せずに表示でき、Web資産へバージョンを書き込まないので、MARKETING_VERSION・CURRENT_PROJECT_VERSIONを上げるだけで表示も変わります。値が無いとき(ブラウザで開いたときなど)は欄を隠したままにします。「サポート」に、不具合の報告へバージョンを添えるよう一文を足しました。
  • App Storeの評価の依頼: StoreKitのシステムの依頼画面(AppStore.requestReview(in:))だけを使います(ios/App/ReviewRequest.swift)。PNG・PDFを「ファイルに保存」で保存し終えたとき、または共有シートで共有を終えたときにだけ判定し、条件を満たすと1秒待ってから依頼します。条件はios/docs/NATIVE_BRIDGE.mdの「App Storeの評価の依頼」に書きました。「プライバシー」に、評価の依頼が出ることがあり編み図は送られない旨を足しました。
  • Web版(Pages)のファイルは変えていません。

決めたこと

Issueの本文とAppleのガイドライン(App Review Guidelines 5.6.1、システムの依頼画面を作業の区切りで出す)に沿って、控えめな条件にしました。

条件 値
依頼を検討する時点 PNG・PDFの保存(Document Pickerで保存完了)または共有(共有シートで完了)の直後だけ。取り消し、.knitの書き出し、編集の途中、起動直後には出さない
初めて起動してからの時間 3日以上(この版より前から使っている端末では、この版を初めて起動した日時から数える)
前回の依頼のあと(初めてなら最初から)のPNG・PDFの保存・共有の回数 3回以上
同じバージョン 一度だけ
前回の依頼からの時間 120日以上
画面の状態 アプリが前面にあり、保存画面・共有シート・警告が出ていない(保存画面が閉じ切るのを1秒待ってから確かめる)
  • 依頼を試みたら版と日時を記録して回数を0に戻します。画面の状態の条件で出せなかったときは記録せず、次の書き出しで改めて判定します。記録はUserDefaults(reviewRequest.で始まるキー)だけに置きます。
  • バージョンの表示場所は「使い方」のフッター(「棒針編み図エディタへ戻る」の下)にしました。編集画面のフッターは feat: 編み図で使っている色の一覧から色を選べるようにする #115 などと重なるため変えていません。
  • 未決定: 「使い方」からApp Storeのレビューを書くページ(https://apps.apple.com/app/id<App ID>?action=write-review)へのリンクは、App IDがリポジトリや公開情報から確定できないため置いていません。[P1] アプリ内にバージョンを表示し、App Storeの評価を依頼する #84 にコメントで残しました。このためClosesではなくRefsにしています。

実行した確認

  • iOS Webの型検査(tsc -p tsconfig.app.json --noEmit)とテスト(vitest run --config vite.config.ts、4ファイル13件。guideVersion.test.tsを追加): 成功
  • ルートのnpm run typecheck、npm test(26ファイル159件): 成功
  • ios/scripts/check-app-store-docs.sh: 成功
  • xcodegen generate --spec ios/project.yml、Xcode 27.0でSimulator向けbuild-for-testing: 警告なしで成功。できたアプリにios/scripts/check-app-bundle.sh: 成功
  • iPad Pro 11-inch (M5)(iOS 27.0)Simulatorで、追加した単体テストReviewRequestPolicyTests・ReviewRequestTrackerTests・AppVersionInfoTestsの20件: 成功
  • 同梱のguide/index.htmlにwindow.knittingEditorAppInfoを与え、PlaywrightのWebKitで幅390px・1024pxに表示して、フッターに「バージョン 1.0(ビルド 1)」が出て横にはみ出さないことを確認

できなかった確認

  • testGuideNavigationReturnsToUsableEditor(使い方ページの末尾のバージョン表示の確認を追加)は手元で通せていません。手元の負荷が非常に高く、1回目は「使い方」のタップで画面が切り替わらず、追加した確認より前の待ち合わせで失敗し、2回目はテストランナーが起動中に停止しました。このUIテストとSimulatorの一式(iPhone・iPad)、アプリ更新テスト、Release ArchiveはこのPRのCIで確かめます。
  • 評価の依頼画面をSimulatorで実際に出す確認はしていません(Simulatorを操作する許可を得られなかったため)。開発ビルドでは毎回表示されるので、reviewRequest.firstLaunchDateを3日以上前に書き換えてPNGかPDFを3回保存すると確認できます。TestFlightでは表示されません。
  • iPhone・iPad Simulatorでの画面の画像は撮れていません。WebKitで描いた「使い方」のフッターの画像は手元にありますが、PRには画像を添付できないため添付していません。
  • Web版のファイルは変えていないため、npm run build・npm run check:dist・npm run test:e2eは実行していません。手元のNode.jsは26(指定は24)です。

懸念

  • 手元の古いSimulatorではreviewRequest.firstLaunchDateが3日以上前になると、XCUITestで何度もPNG・PDFを保存するうちに開発ビルドの依頼画面が出て、UIテストの邪魔をするおそれがあります。CIは毎回新しいSimulatorなので出ません。
  • 未マージの fix: iOS版を明るい配色に固定し、起動画面から編集画面までの色をそろえる #118 もWebViewContainer.swiftとproject.pbxprojを変えています。後から入る側でxcodegen generateの再実行が必要になる場合があります。

レビューでの修正(2026-10-07)

  • Privacy Manifest: 評価の依頼の判定でUserDefaultsを使うため、ios/App/PrivacyInfo.xcprivacyのNSPrivacyAccessedAPITypesにNSPrivacyAccessedAPICategoryUserDefaults(理由CA92.1)を足しました。ios/AppのSwiftを調べ、ほかの申告対象(ファイルのタイムスタンプ、起動時刻、ディスク容量、有効なキーボード)は使っていないことを確かめました。
  • 再発防止: ios/scripts/check-app-bundle.shが、アプリの実行ファイル(Debugでは*.debug.dylibも)の取り込むシンボルと文字列から申告対象のAPIの利用を調べ、理由つきの申告が無ければ失敗するようにしました。CIのiosジョブと、check-release-assets.sh経由でrelease_archiveジョブで動きます。
  • プライバシーポリシー: ios/docs/PRIVACY_POLICY.mdの「端末内での保存」に、評価の依頼の時期を判断するための記録(初めて起動した日時、PNG・PDFを保存・共有した回数、最後に依頼した日時とバージョン)を端末内にだけ置き、外部へ送らないことを足し、改定日を更新しました。ios/docs/APP_STORE_CHECKLIST.mdにも申告と検査を書きました。
  • 確認: plutil -lint、xcodegen generate(project.pbxprojに差分なし)、Xcode 27.0でのSimulator向けbuild-for-testingとcheck-app-bundle.sh、Release構成の署名なしArchiveとcheck-release-assets.shが成功。Privacy Manifestを修正前の空のもの・理由が空のもの・別の種類だけのものに差し替えたアプリでは、どちらの検査もUserDefaultsの申告漏れとして失敗することを確かめました。check-app-store-docs.shも成功。Simulatorのテスト一式はCIで確かめます。

Refs #84

🤖 Generated with Claude Code

…xports

iOS版の「使い方」の末尾に、Info.plistから渡したバージョンとビルド番号を表示する。
PNG・PDFの保存・共有を終えた区切りでだけ、条件を満たすとStoreKitのシステムの
依頼画面で評価を依頼する。条件はios/docs/NATIVE_BRIDGE.mdに書いた。

Refs #84

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@K0mork K0mork added the enhancement New feature or request label Oct 6, 2026
Copilot AI balanced review requested due to automatic review settings October 6, 2026 12:48

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@K0mork K0mork left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

レビュー(CIの結果と確認したこと)

CI(run 37465916953、head 043767f)

すべて成功し、ci-gate も成功しました(web は Web 版の変更が無いため skip)。

  • ios (iPhone 17)・ios (iPad (A16)): 単体テスト46件(既存の機内モード用1件 skip)、UIテスト18件(既存の5件 skip)が成功。手元で通せなかった testGuideNavigationReturnsToUsableEditor は両端末で passed で、追加したバージョン表示の確認も通っています。追加した ReviewRequestPolicyTests(8件)・ReviewRequestTrackerTests(8件)・AppVersionInfoTests(4件)も両端末で成功。
  • app_update (iPhone 17)・app_update (iPad (A16))・release_archive(Release Archive と check-release-assets.sh)・ios_web・app_store_docs・changes・CodeQL: 成功。

確かめて問題が無かった点

  • バージョン・ビルド番号は Info.plist から読み、JSON として WKUserScript(文書の読み込み開始時・メインフレームだけ)で渡しており、通信なしで表示できる。ページ側は textContent で表示し、値が無い・不正なときは hidden のまま。Web 版(Pages)の使い方ページは変わっていない。
  • 評価の依頼は AppStore.requestReview(in:) だけを使い、独自の評価ダイアログやボタンは無い(App Review Guidelines 5.6.1 に沿う)。iOS 17 以上の対象なので API の可用性も問題ない。
  • 判定は Document Picker の保存完了と共有シートの completed == true でだけ行われ、取り消し・.knit(application/gzip)・編集途中・起動直後(初回起動から3日未満)は対象外。待機後に再判定し、前面で他の画面が出ていないことも確かめている。
  • UIテストは PNG・PDF の書き出しを警告の「キャンセル」で閉じるため回数が増えず、UIテストの保存操作を邪魔しない(PR本文の懸念は CI では起きない)。
  • project.pbxproj は xcodegen generate の出力と一致(差分なし)。
  • docs/dev-log/ のエントリは書式どおりで、件数(Swift 20件など)も CI の結果と合っている。差分・PR本文・コミットメッセージに App ID やチームIDなどの機密情報は無く、Refs #84 と enhancement ラベルがある。

直すべき点

  1. 【高】Privacy Manifest に UserDefaults の利用理由が無い: このPRで初めてアプリが UserDefaults を使うようになりましたが、ios/App/PrivacyInfo.xcprivacy の NSPrivacyAccessedAPITypes は空のままです。UserDefaults は Apple の「理由の申告が必要な API」に当たり、申告が無いと App Store Connect へのアップロード時に ITMS-91053(Missing API declaration)となり受け付けられません。CI の Archive は署名・アップロードをしないため検出できていません。次の項目を足してください。

    <key>NSPrivacyAccessedAPITypes</key>
    <array>
      <dict>
        <key>NSPrivacyAccessedAPIType</key>
        <string>NSPrivacyAccessedAPICategoryUserDefaults</string>
        <key>NSPrivacyAccessedAPITypeReasons</key>
        <array><string>CA92.1</string></array>
      </dict>
    </array>

    あわせて dev-log に追記し、可能なら check-app-bundle.sh などで「UserDefaults を使うなら申告がある」ことを検査すると再発を防げます。

  2. 【低】公開のプライバシーポリシーとの整合: アプリ内の「使い方」には評価の依頼について追記されましたが、ios/docs/PRIVACY_POLICY.md(「端末内での保存」)には、評価の依頼の判定のために書き出しの回数と日時を端末内に記録すること(外部へは送らない)が書かれていません。App Store に登録するポリシーと内容を揃えるため、一文足すことを勧めます。

利用者の判断が必要な点

  • #84 の残り(「使い方」に App Store のレビューを書くページへのリンクを置くか)は App ID が決まるまで未決定です。このため Closes ではなく Refs のままで妥当です。
  • 依頼画面が実際に表示されることの確認(開発ビルドの Simulator で reviewRequest.firstLaunchDate を3日以上前にして PNG・PDF を3回保存)はまだ行われていません。TestFlight では表示されないため、確認するなら Simulator か開発ビルドの実機で行う必要があります。

マージはしていません。

…reason APIs

評価の依頼の判定で使うUserDefaultsを、Privacy Manifestに理由CA92.1で申告する。
check-app-bundle.shで、アプリが使う理由の申告が必要なAPIに申告があることを検査する。
プライバシーポリシーに、評価の依頼のための記録を端末内にだけ置くことを足す。

Refs #84

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@K0mork

K0mork commented Oct 6, 2026

Copy link
Copy Markdown
Owner Author

レビュー指摘の修正(704fc11)

  • 【高】Privacy Manifest: NSPrivacyAccessedAPITypesにNSPrivacyAccessedAPICategoryUserDefaults(理由CA92.1)を足しました。ios/AppのSwiftにほかの申告対象(ファイルのタイムスタンプ、起動時刻、ディスク容量、有効なキーボード)の利用はありません。
  • 再発防止: ios/scripts/check-app-bundle.shが、アプリの実行ファイル(Debugでは*.debug.dylibも)の取り込むシンボルと文字列から申告対象のAPIの利用を調べ、理由つきの申告が無ければ失敗するようにしました。修正前の空のManifest・理由が空のもの・別の種類だけのものに差し替えたアプリ(Debug・Release Archiveとも)で失敗することを確かめています。
  • 【低】プライバシーポリシー: 「端末内での保存」に、評価の依頼の時期を判断するための記録を端末内にだけ置き、外部へ送らないことを足し、改定日を更新しました。APP_STORE_CHECKLIST.mdとdocs/dev-log/にも追記しています。

CI(run 37496536632)

すべて成功し、ci-gateも成功しました(webはWeb版の変更が無いためskip)。ios (iPhone 17)・ios (iPad (A16))・app_update(両端末)・release_archive・ios_web・app_store_docs・changes・CodeQLが成功。ios両端末の「Verify generated app bundle」とrelease_archiveの「Verify archived app bundle」で、追加した申告の検査も通っています。

マージはしていません。

…ew-request

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@K0mork
K0mork merged commit e58260c into main Oct 7, 2026
15 checks passed
@K0mork
K0mork deleted the feat/version-and-review-request branch October 7, 2026 02:51
K0mork added a commit that referenced this pull request Oct 7, 2026
Keep both sides in WebViewContainer.swift: the launch colors and loading
style from #118, and the menu command state and native UI flag from #125.
The share sheet completion now clears the native UI flag and reports the
finished export for the review request (#121). Regenerate project.pbxproj
with XcodeGen.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@K0mork

K0mork commented Oct 7, 2026

Copy link
Copy Markdown
Owner Author

マージ後の確認です。

  • main の CI and deploy Pages(run 37563989434、e58260c)は成功しました。ios(iPhone 17・iPad (A16))、app_update(両端末)、release_archive、ios_web、ci-gate が成功しています。
  • iOS だけの変更なので web・deploy・smoke はスキップされ、Pages の配信には影響しません。
  • 残っている確認: 評価の依頼画面が実際に出ること(開発ビルドの Simulator か実機)、レビューページへのリンクを置くか(App ID の確定後。[P1] アプリ内にバージョンを表示し、App Storeの評価を依頼する #84 は開いたまま)。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants