App ReviewでiOSアプリをRejectされた理由とその解決策

iOSアプリをリリースする場合、Appleによるアプリの審査「App Review」を突破する必要があります。
何度かのRejectとその対策を経て、無事初めてのiOSアプリをリリースできたので、備忘録としてRejectの内容とその解決策を書き残しておきます。

## 理由その1:iPad用のスクリーンショットがない
Appleからのメールに記載されたRejectの理由は下記の通り。

> Guideline 2.3.3 - Performance - Accurate Metadata
> 
> Issue Description
> 
> The iPad screenshots show an iPhone device frame. Screenshots should highlight the app's core concept to help users understand the app’s functionality and value.
> 
> Next Steps
> 
> Upload new screenshots that resolve the issues identified above and accurately reflect the app in use on each of the supported devices.
> （以下略）

こちらをDeepLで翻訳すると、

> ガイドライン2.3.3 - パフォーマンス - 正確なメタデータ
> 
> 問題の説明
> 
> iPadのスクリーンショットにiPhoneのフレームが表示されている。スクリーンショットは、ユーザーがアプリの機能と価値を理解できるように、アプリのコアコンセプトを強調する必要があります。
> 
> 次のステップ
> 
> 上記の問題を解決し、サポートされている各デバイスで使用されているアプリを正確に反映した新しいスクリーンショットをアップロードしてください。
> 
> （以下略）
> DeepL.com（無料版）で翻訳しました。

これは単純に、iPad時のUIのスクリーンショットが無いからアップロードしなさいよ、ということでした。

## 解決策その1: iPad時のスクリーンショットをアップロードする
Apple Developerから、iPad時のスクリーンショット（**W2,752px × H2,064px**）を登録する。
![ipad.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2781928/567eae71-f154-4bb2-b402-e23b35f94f7d.png)


## 理由その2:写真・カメラにアクセスする目的が明確に示されていない

Appleからのメールに記載されたRejectの理由は下記の通り。

> Guideline 5.1.1 - Legal - Privacy - Data Collection and Storage
> 
> Issue Description
> 
> One or more purpose strings in the app still do not sufficiently explain the use of protected resources. Purpose strings must clearly and completely describe the app's use of data and, in most cases, provide an example of how the data will be used.
> 
> Next Steps
> 
> Update the photo library purpose string to explain how the app will use the requested information and provide a specific example of how the data will be used. See the attached screenshot.
> （以下略）

こちらをDeepLで翻訳すると、

> ガイドライン5.1.1 - 法的 - プライバシー - データの収集と保管
>
> 問題の説明
>
> アプリ内の1つ以上の目的文字列が、保護されたリソースの使用についてまだ十分に説明していない。目的文字列は、アプリのデータ使用を明確かつ完全に説明し、ほとんどの場合、データの使用方法の例を提供する必要があります。
>
> 次のステップ
>
> フォトライブラリの目的文字列を更新し、アプリが要求された情報をどのように使用するかを説明し、データがどのように使用されるかの具体例を提供する。添付のスクリーンショットを参照してください。
> （以下略）
> DeepL.com（無料版）で翻訳しました。

提出したアプリには、ユーザーの写真データとカメラにアクセスする機能を実装していたのですが、写真・カメラにアクセスする前に表示されるalertの文言が不十分ですよ、という指摘。

## 解決策その2:Info.plistの値を修正

アプリが写真・カメラにアクセスする前に、alertを表示してアクセスの可否をユーザーに問う必要があります。そのalertに表示される文字列は、Info.plistに`NSCameraUsageDescription`と`NSPhotoLibraryUsageDescription`として記載されています。
今回の場合は、以下のように文言を修正することで審査をクリアしました。
「アプリ内での使用目的」は過不足のない範囲で具体的に書いておくと、審査が通りやすくなるのかもしれません。

```Info.plist
<key>NSCameraUsageDescription</key>
<string>{アプリ内での使用目的}のために、このアプリにカメラへのアクセスを許可しますか？</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>{アプリ内での使用目的}のために、このアプリにカメラロールへのアクセスを許可しますか？</string>
```


## 理由その3:アプリの初回起動時にトラッキングの可否をユーザーに聞いていない

Appleからのメールに記載されたRejectの理由は下記の通り。

> Guideline 5.1.2 - Legal - Privacy - Data Use and Sharing
> 
> The app privacy information provided in App Store Connect indicates the app collects data in order to track the user, including Coarse Location and Advertising Data. However, the app does not use App Tracking Transparency to request the user's permission before tracking their activity.
> 
> Apps need to receive the user’s permission through the AppTrackingTransparency framework before collecting data used to track them. This requirement protects the privacy of users.
> 
> Next Steps
> 
> Here are three ways to resolve this issue:
> 
> - If the app does not currently track, update the app privacy information in App Store Connect. You must have the Account Holder or Admin role to update app privacy information. If you are unable to change the privacy label, reply to this message in App Store Connect, and make sure your App Privacy Information in App Store Connect is up to date before submitting your next update for review.
> 
> - If this app does not track on the platform associated with this submission, but tracks on other platforms, notify App Review by replying to the rejection in App Store Connect.
> 
> - If the app tracks users on all supported platforms, the app must use App Tracking Transparency to request permission before collecting data used to track. When resubmitting, indicate in the Review Notes where the permission request is located.
> 
> Note that if the app behaves differently in different countries or regions, you should provide a way for App Review to review these variations in the app submission. Additionally, these differences should be documented in the Review Notes section of App Store Connect.
> （以下略）

こちらをDeepLで翻訳すると、

> ガイドライン5.1.2 - 法的 - プライバシー - データの使用と共有
> 
> App Store Connectで提供されるアプリのプライバシー情報は、アプリがユーザーを追跡するために、粗い位置情報と広告データを含むデータを収集することを示しています。しかし、アプリは、ユーザーの行動を追跡する前にユーザーの許可を求めるために、App Tracking Transparencyを使用していません。
> 
> アプリは、ユーザーを追跡するために使用されるデータを収集する前に、AppTrackingTransparencyフレームワークを通じてユーザーの許可を得る必要があります。この要件は、ユーザーのプライバシーを保護します。
> 
> 次のステップ
> 
> この問題を解決するには、次の3つの方法があります：
> 
> - アプリが現在トラッキングしていない場合は、App Store Connectでアプリのプライバシー情報を更新します。アプリのプライバシー情報を更新するには、アカウント所有者または管理者のロールが必要です。プライバシーラベルを変更できない場合は、App Store Connectでこのメッセージに返信し、App Store Connectのアプリプライバシー情報が最新であることを確認してから、次の更新を審査に提出してください。
> 
> - このアプリが、この提出に関連付けられたプラットフォームではトラッキングされないが、他のプラットフォームではトラッキングされる場合、App Store Connectで却下に返信することにより、App Reviewに通知してください。
> 
> - アプリがサポートされるすべてのプラットフォームでユーザーを追跡する場合、アプリは、追跡に使用するデータを収集する前に、App Tracking Transparencyを使用して許可を要求する必要があります。再提出の際には、レビューノートに許可申請の場所を記載してください。
> 
> 国や地域によってアプリの動作が異なる場合は、アプリの提出時にApp Reviewがこれらの差異をレビューする方法を提供する必要があることに注意してください。さらに、App Store ConnectのReview Notesセクションにこれらの違いを記録してください。
> 
> （以下略）
> DeepL.com（無料版）で翻訳しました。

提出したアプリにはAdMobによる広告枠を設置していたのですが、ここに出稿する広告をカスタマイズする目的でユーザーデータを収集するため、アプリの初回起動時にユーザーに対してその旨を伝える必要があるのに、そのプロセスがないよ、という指摘でした。

## 解決策その3：アプリ初回起動時にトラッキングの可否を問う処理を追加
ユーザーがアプリをインストールして初めて起動するタイミングで、ユーザーにトラッキングの可否を問うalertを表示する処理を追加しました。
まず、Info.plistに`NSUserTrackingUsageDescription`とその値を追加します。

```Info.plist
<key>NSUserTrackingUsageDescription</key>
<string>アプリ内であなたの興味・関心に沿った広告を表示するために、このアプリにトラッキングを許可しますか？</string>
```

そして、Inital View Controllerに指定しているviewControllerの`viewDidAppear`のタイミングで、以下のようにalertを表示する機能を追加して再度提出したところ、審査を通過できました。

```swift
import UIKit
import AppTrackingTransparency

class ViewController: UIViewController {

//トラッキングの可否選択（アプリのインストール後、初回起動時のみ）
    override func viewDidAppear(_ animated: Bool) {
            super.viewDidAppear(animated)
            showTrackingPermissionAlertIfNeeded()
        }
        
        private func showTrackingPermissionAlertIfNeeded() {
            // すでに表示済みならスキップ
            let hasShownTrackingAlert = UserDefaults.standard.bool(forKey: "hasShownTrackingAlert")
            if hasShownTrackingAlert { return }
            self.requestTrackingAuthorization()
        }
        
        private func requestTrackingAuthorization() {
            guard #available(iOS 14, *) else { return }

            ATTrackingManager.requestTrackingAuthorization { status in
                DispatchQueue.main.async {
                    // ステータスに関係なく、1回表示したので記録
                    UserDefaults.standard.set(true, forKey: "hasShownTrackingAlert")
                }
            }
        }
}
```

## 所感
「最初は何度かRejectされる！」と噂には聞いていたのですが、実際にリリースしてみたところ、
Rejectの主な理由はユーザーデータへのアクセスまわりだったので、
Info.plistに値を適切に設定し、アプリの初回起動時にその値をしっかりユーザーに提示する、
という点に注意してアプリを修正すると、きちんと承認されてリリースまで漕ぎ着けることができました。
「同じような理由でRejectされてどうしたらいいか分からん！」という方の参考になれば幸いです。