個人開発 iOS アプリの Privacy Manifest 対応チェックリスト
AI 主体で執筆なぜ今これが必要か
Apple は 2024 年以降、アプリに Privacy Manifest(PrivacyInfo.xcprivacy)の同梱と、一部 API の使用理由の宣言を審査時の必須条件に組み込んだ。
個人開発者にとっては、「UIKit の一部メソッドを呼んだだけで警告が出る」「第三者 SDK のせいで審査が通らない」という、それまで気にしなくてよかったレイヤーの問題が増えた。
この記事は、60d Memo v1.0 を App Store に通した実例をもとに、個人開発者が最低限やっておくべき対応を具体的にチェックリスト化する。
対象読者: iOS 17+ を最低サポートとする個人開発者。SwiftUI + SwiftData + 数個の SPM 依存、くらいのシンプルな構成を想定。
Privacy Manifest とは何か
PrivacyInfo.xcprivacy は、アプリがどんなデータにアクセスし、何のために使うかを機械可読な形で宣言する plist ファイルだ。
主に次の 4 項目を宣言する:
| キー | 内容 | 60d Memo の例 |
|---|---|---|
NSPrivacyTracking |
トラッキングを行うか | false |
NSPrivacyTrackingDomains |
トラッキングに使うドメイン | 空配列 |
NSPrivacyCollectedDataTypes |
収集するデータの種類 | 空配列(自前サーバーに何も送らない) |
NSPrivacyAccessedAPITypes |
Required Reason API の使用理由 | 後述(UserDefaults など) |
Required Reason API とは
「使った場合に理由宣言が必須になる」と Apple が指定した API 群。プライバシー上のリスクがある(フィンガープリンティングに使われうる)API が対象。
典型的な対象 API
UserDefaults— 設定保存などで必ず使う。宣言理由:CA92.1(アプリ自身のため)FileManager.default.attributesOfItem(atPath:)などのファイルタイムスタンプ系systemUptime- ディスク空き容量取得系 API
- アクティブキーボード取得
公式リスト: Describing use of required reason API
注意: 宣言漏れがあると App Store 審査で警告が出る。自分のコードに加え、依存している SPM ライブラリ内での使用も対象になりうる。
60d Memo v1.0 の実例
最小構成の PrivacyInfo.xcprivacy
60d Memo は:
- 自前サーバーにデータを送らない(Google Drive はユーザー自身の領域)
- トラッキングなし・広告なし
UserDefaultsでユーザー設定を保存
この構成で必要だった宣言は次のとおり:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSPrivacyTracking</key>
<false/>
<key>NSPrivacyTrackingDomains</key>
<array/>
<key>NSPrivacyCollectedDataTypes</key>
<array/>
<key>NSPrivacyAccessedAPITypes</key>
<array>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>CA92.1</string>
</array>
</dict>
</array>
</dict>
</plist>
これだけで v1.0 は審査を通過した。重要なのは自分のアプリ本当の挙動と宣言が一致していること。実際にやっていない行為(データ収集、トラッキング)を false で宣言するだけ。
配置場所
アプリのメインターゲット直下に PrivacyInfo.xcprivacy を置き、Xcode プロジェクトに追加する(Copy Bundle Resources に含まれるはず)。
第三者 SDK の確認
SDK 側も Privacy Manifest を同梱している必要がある。Apple が指定する「commonly used SDK」リストに入っているものは特に注意。
60d Memo では
唯一の SPM 依存が GoogleSignIn-iOS。これは Google 公式が Privacy Manifest を同梱済みで、特に追加作業は不要だった。
確認方法
- 依存 SDK のリポジトリで
PrivacyInfo.xcprivacyを検索 - 見つからなければ、SDK のリリースノート / CHANGELOG で対応バージョンを確認
- 古いバージョンを使っているなら、Privacy Manifest 同梱版にアップデート
注意: SDK を束ねた xcframework / バイナリ配布を使っている場合、その中に Privacy Manifest が入っているかは自分では変えられない。提供元の更新を待つしかない。
ログのプライバシー(OSLog の privacy: パラメータ)
Privacy Manifest と直接の関係はないが、実装上は一緒に対応すべき。print() ではなく Logger(import os)を使い、機微情報には privacy: を明示する。
import os
private let logger = Logger(subsystem: "dev.60d.memo", category: "sync")
// 機微情報: .private で Release ビルドではマスクされる
logger.info("Signed in as \(email, privacy: .private)")
// メタデータ(ID、ステータスコード等)は .public で OK
logger.debug("Syncing memo \(memoId, privacy: .public)")
// Release で確実に出したくないならビルド時に除外
#if DEBUG
logger.debug("Response body: \(bodyString, privacy: .public)")
#endif
重要なのは、指定省略時のデフォルトは .public ということ。うっかりメールアドレスやトークンが本番ログに出続けないよう、機微情報には必ず privacy: を書く。
ログに絶対出さないもの
- OAuth アクセストークン / リフレッシュトークン
- メールアドレス全文(ドメイン部だけならまだ妥協可)
- ユーザーのメモ本文やコンテンツ
- 決済情報
チェックリスト
初回リリース前に
PrivacyInfo.xcprivacyを作成してアプリターゲットに追加NSPrivacyTracking/NSPrivacyCollectedDataTypesを実態に合わせて宣言- 使っている Required Reason API を洗い出して
NSPrivacyAccessedAPITypesに記載 - 依存 SDK が Privacy Manifest 対応バージョンか確認
- App Store Connect の「App Privacy」セクションも Privacy Manifest と整合させる
- ログ出力を
print()→Loggerに置き換え - 機微情報に
privacy: .private/.sensitiveを明示
新しい API を使ったとき
- その API が Required Reason API かを公式リストで確認
- 該当すれば
PrivacyInfo.xcprivacyに追記 - 該当しなくても、機微情報をログに出していないか再確認
新しい SDK を追加するとき
- SDK 側が Privacy Manifest を同梱しているか
- SDK が使う Required Reason API が、アプリ側の宣言と一致しているか
- SDK が内部でトラッキングを行うなら、
NSPrivacyTrackingを再検討
トラブルシューティング
「Missing API declaration」の警告
App Store Connect のアップロード後、メールで「ITMS-91053」のような警告が来る。該当する API カテゴリを PrivacyInfo.xcprivacy に追加する。
自分は使っていないのに警告が出る
多くの場合、依存 SDK 内の使用が原因。SDK を新しいバージョンにアップデートするか、SDK のドキュメントで推奨される対応を確認する。
審査で差し戻された
実態と宣言が食い違っているケースが多い。特に:
- Firebase / Analytics 系 SDK を入れているのに
NSPrivacyTrackingがfalse - 広告 SDK を使っているのに収集データを宣言していない
レビューアからのコメントを文字通り読んで、自分の実装と照らし合わせる。
個人開発で「最小で通す」戦略
Privacy Manifest の網羅は大変なので、個人開発ではシンプルな設計自体が最強の審査対策になる。
- 第三者 SDK を最小限に — Apple 標準フレームワークだけなら宣言もシンプル
- トラッキング・広告 SDK は入れない — 宣言漏れのリスクが消える
- ユーザーデータを自前サーバーに送らない —
NSPrivacyCollectedDataTypesが空でよい
60d Memo は「データの所有権をユーザーに返す」というコンセプトで設計したため、結果的に Privacy Manifest の宣言が最小で済んだ。プライバシー重視の設計は、ユーザーのためだけでなく開発者自身の工数削減にもつながる。
まとめ
Privacy Manifest は面倒に見えて、次のステップで整理できる:
- 自分のアプリの実態(トラッキング・データ収集)を素直に宣言
- 使っている Required Reason API を洗い出して理由を記載
- 依存 SDK が対応バージョンか確認
- ログ出力の機微情報を
privacy:パラメータで保護
複雑に見えるが、シンプルなアプリほど宣言は軽い。「複雑なデータ処理をしない」設計そのものが最も確実な対策だ。
最後に、発見した制約や API はプロジェクトのルールファイルに蓄積することを勧める。次のアプリ、次のリリースで同じ調査を繰り返さなくて済む。これについては別の記事で詳しく書いた。