# Guideline 1.2 使用者生成內容：Apple 的要求

> 使用者會發布內容的 App，要有過濾、檢舉、封鎖、聯絡方式與已同意的使用條款。附 Expo 與 Supabase 檢查清單。

原始頁面：[Guideline 1.2 使用者生成內容：Apple 的要求](https://devoria.fr/zh-hant/blog/guideline-1-2-user-generated-content-apple)
作者：[Mehdi Azizi](https://devoria.fr/zh-hant/mehdi-azizi)
發布日期：2026-11-04
內容最後修訂：2026-11-04


只要使用者發布的東西會被其他人看到，guideline 1.2 就適用：一則訊息、一張照片、一篇評論，在我看來，連排行榜上的一個暱稱都算。這時 Apple 的條文要求四件事：過濾機制、可檢舉且快速回應、封鎖功能，以及公開的聯絡方式。**退件訊息還多加了第五項要求：使用者必須同意使用條款，而且條款明訂不容忍不當內容與濫用的使用者。**

這篇指南不是在講某次被退件的經過。它要分享的是，我的交易練習 App TradaZen 的排行榜開始顯示玩家自取的暱稱時，我做了哪些措施。如果想看所有退件原因的總覽，請改讀[Apple 為什麼退你的 App](https://devoria.fr/zh-hant/blog/apple-app-rejection-reasons-real-cases)。

## guideline 1.2 寫了什麼？

1.2「User-Generated Content」位於 [App Review Guidelines](https://developer.apple.com/app-store/review/guidelines/#user-generated-content) 第 1 節「Safety」。它針對有使用者內容或社群網路服務的 App。為了防止濫用，這類 App「must include」四項保護：

- 「A method for filtering objectionable material from being posted to the app」：**在發布前擋下不當內容的過濾機制**。
- 「A mechanism to report offensive content and timely responses to concerns」：檢舉內容的方法，以及對檢舉的快速回應。
- 「The ability to block abusive users from the service」：封鎖濫用者的功能。
- 「Published contact information so users can easily reach you」：公開且容易找到的聯絡方式。

目前版本的條文在 2026 年 6 月 8 日更新，要求更進一步。它提醒你：移除違反規定、違反你的使用條款或社群守則的內容，是你的責任。如果 Apple 發現這類內容，會要求你移除並提出改善計畫，在那之前還可能把 App 下架。

條文也列出了不適合上架 App Store 的 App：主要用於色情、像 Chatroulette 那樣的隨機或匿名聊天、替真人的外貌評分、威脅或騷擾的 App。**這些用途光有四項保護是不夠的。** 1.2.1 則為創作者 App 增加了規定，特別是內容超出 App 分級時要做年齡驗證。

## 你的 App 適用嗎？

App Store Connect 的年齡分級問卷給了不錯的定義。當使用者建立的內容（影片、照片、文字或音訊）在 App 中被廣泛散布，它就稱為[使用者生成內容](https://developer.apple.com/help/app-store-connect/reference/app-information/age-ratings-values-and-definitions)。使用者之間的訊息則另外處理。

| 其他人看得到的東西 | 適用嗎？ |
| ------------------ | -------- |
| 會員之間的訊息     | 是       |
| 公開的照片或評論   | 是       |
| 排行榜上的暱稱     | 我認為是 |
| 私人筆記           | 否       |
| 你自己寫的內容     | 否       |

Apple 沒有提到暱稱。但我還是把它當成使用者內容：任何人都能取一個侮辱性的暱稱，而其他玩家看得到。這是我為 TradaZen 排行榜做的選擇。

## 用 Expo 和 Supabase 實作的 5 個機制

一位開發者在 2025 年底把 1.2 的退件訊息貼到 [Apple 論壇](https://developer.apple.com/forums/thread/807358)，裡面列出了預期的措施。它以「Require that users agree to terms (EULA)」開頭，最後是時限要求：在「within 24 hours」內處理檢舉，移除內容並把發布者踢出。

| 機制         | 在哪裡實作            |
| ------------ | --------------------- |
| 已同意的條款 | 畫面與個人資料        |
| 過濾         | 伺服器，顯示前        |
| 檢舉         | 按鈕與資料表          |
| 封鎖         | 資料表與存取規則      |
| 公開聯絡方式 | App 與 App Store 頁面 |

下面的 SQL 範例請依你的 schema 調整。它們使用 [Supabase 的列層級存取規則](https://supabase.com/docs/guides/database/postgres/row-level-security)，就算有人繞過你的 App 也照樣生效。

### 1. 已同意的使用條款，對濫用零容忍

你的使用條款必須白紙黑字寫明不容忍任何不當內容或濫用的使用者。條款範例（請找人審閱，這不是法律意見）：「不容忍任何冒犯、仇恨、色情或騷擾內容。被檢舉的內容可能被移除，發布者可能被停權，恕不另行通知。」

**註冊按鈕下方一句被動的說明，無法證明使用者同意：要讓對方做出明確的動作。** 在第一次發布前，放一個附條款連結和「我同意」按鈕的畫面。把同意的日期和版本存進個人資料，缺少時就禁止發布：

```sql
create policy "publier après les CGU" on public.posts
for insert to authenticated
with check (
  auth.uid() = author_id
  and exists (
    select 1 from public.profiles p
    where p.id = auth.uid() and p.cgu_acceptees_le is not null
  )
);
```

### 2. 在其他人看到之前過濾

過濾放在伺服器上，因為 App 的程式碼可以被繞過。App 裡的副本只是用來立即提醒使用者。

在 TradaZen，資料庫裡的一個函式會檢查每個暱稱，App 也套用同一份清單來提醒玩家。我讓兩邊保持一致。在伺服器端，冒犯性的暱稱不會在寫入時被拒絕：**而是在顯示時換成中性暱稱，這樣就不會因為誤判而擋住某個人**。

誤判很快就會出現。在 TradaZen，早期版本的過濾器會審查 Dominique、Monique、Véronique 這類名字，因為它們包含髒話的片段。修正方式：比對完整的單字，而不是單字片段。另外，App 也以日文和中文販售，所以過濾器也涵蓋這些語言。

### 3. 檢舉，24 小時內處理

每則發布的內容都有一個「檢舉」按鈕。在 TradaZen，聯盟排行榜中被檢舉的暱稱，會立刻在檢舉者的手機上以中性名稱顯示。接著檢舉會送到伺服器，如果手機離線就之後再送。

資料庫端用一張檢舉資料表，每人每則內容只能檢舉一次：

```sql
create table public.reports (
  id uuid primary key default gen_random_uuid(),
  reporter_id uuid not null references auth.users (id) on delete cascade,
  target_id uuid not null,
  reason text,
  created_at timestamptz not null default now(),
  unique (reporter_id, target_id)
);
alter table public.reports enable row level security;
create policy "mes signalements" on public.reports
for insert to authenticated
with check (auth.uid() = reporter_id);
```

在 TradaZen，**被多位玩家檢舉的暱稱會換成中性暱稱**，而且被檢舉的人永遠看不到檢舉內容。一個通用的預防措施：用於檢舉的識別碼不能讓內容作者修改，否則他可以躲過隱藏。

自動隱藏無法取代你的決定。要守住 24 小時，就要讓每次檢舉都通知你：[Supabase 資料庫 webhook](https://supabase.com/docs/guides/database/webhooks) 可以呼叫一個伺服器函式來傳訊息給你。能移除內容的金鑰留在伺服器上，我在[Expo App 的秘密 API 金鑰](https://devoria.fr/zh-hant/blog/expo-api-key-security-supabase)裡有說明。

### 4. 立即生效的封鎖

一張封鎖資料表，再加上一條存取規則，把被封鎖者的內容從封鎖者的動態中移除：

```sql
create policy "sans les bloqués" on public.posts
for select to authenticated
using (
  not exists (
    select 1 from public.blocks b
    where b.blocker_id = auth.uid() and b.blocked_id = posts.author_id
  )
);
```

在 TradaZen，用代碼加好友，也可以移除並封鎖對方。**被封鎖的好友會從清單中消失，就算他再送一次邀請也一樣。**

### 5. 公開且容易找到的聯絡方式

在 App 的設定裡放一個聯絡信箱，並在 App Store Connect 填一個真的有人回應的支援網址。在 TradaZen，支援信箱寫在隱私權政策和使用條款裡。這些頁面該有的內容，請看[App 隱私權政策](https://devoria.fr/zh-hant/blog/ios-app-privacy-policy-guide)。

最後一點：決定使用者刪除帳號後，他的內容要怎麼處理。上面的 `on delete cascade` 會在刪除帳號時一併刪掉他的檢舉。完整做法請看[iOS 帳號刪除](https://devoria.fr/zh-hant/blog/ios-app-account-deletion-test-before-apple-review)。

## TradaZen 在隱私權政策裡寫了什麼

這些機制都公開寫在 TradaZen 的隱私權政策裡，2026 年 9 月隨著聯盟和好友功能上線而補充：「暱稱會經過自動過濾；你可以在排行榜中檢舉不當暱稱，也可以移除並封鎖好友。」同一份政策也說明，電子郵件和日誌永遠不會顯示給其他玩家。App 的背景請看[TradaZen 案例分析](https://devoria.fr/zh-hant/blog/tradazen-case-study-launch-iphone-app)。

## 被 1.2 退件後怎麼回覆 Apple

在回覆和審查備註裡，告訴審查員每個機制在哪裡。這些功能存在於 App 裡：審查員測試的是 build 內的程式碼，所以要準備新的 build。[回覆 App Review](https://developer.apple.com/help/app-store-connect/manage-submissions-to-app-review/reply-to-app-review-messages/) 的流程和其他規定一樣。以下是英文範本，請依需求調整，只保留你的 App 裡真的有的項目：

```text
Hello,

Thank you for your review. Build X includes the precautions
listed in Guideline 1.2:

- Terms: users accept our terms, with zero tolerance for
  objectionable content and abusive users, before posting.
- Filter: posts and usernames are checked on our server
  before other users can see them.
- Report: tap "..." on any post, then "Report".
- Block: tap "..." on any post, then "Block user". Their
  content disappears immediately.
- Reports notify us instantly; we act on them within 24 hours.
- Contact: Settings > Contact us, and our support URL.

Best regards,
```

如果 build 裡少了某個機制，光靠回覆是不夠的。就像 [guideline 2.1](https://devoria.fr/zh-hant/blog/app-store-guideline-2-1-rejection-fix) 一樣，Apple 評判的是它手上的 build。

## 送審前的 1.2 檢查清單

- 你列出了使用者發布、其他人看得到的所有東西，包括暱稱。
- 你的使用條款禁止不當內容和濫用，App 會要求明確點選「我同意」。
- 過濾在伺服器上執行，比對完整單字，並涵蓋你商店頁面的語言。
- 每則內容都有「檢舉」按鈕，每次檢舉都會立即通知你。
- 你能在 24 小時內移除內容並把發布者停權。
- 封鎖使用者會立即移除他的內容。
- App 裡看得到聯絡信箱，支援網址也有回應。
- 年齡分級問卷有申報使用者內容，App 有訊息功能的話也一併申報。
- 審查備註寫明每個機制在哪裡，並附上示範帳號。

## 重新送審前先修正退件問題

如果你的 App 剛因 1.2 被退件，[Review Kit](https://devoria.fr/zh-hant/kits/app-review) 收錄了我每次送審前會檢查的項目，還有兩個 skill 會在 Claude Code 裡檢查你的專案，並在 Apple 退件時幫你準備回覆。想要真人幫你看，[跟我預約一小時](https://devoria.fr/zh-hant/coaching)：我們一起讀退件訊息，檢查你的審核流程。退件後的完整做法在[被 Apple 退件的 App](https://devoria.fr/zh-hant/expertise/app-rejected-by-apple) 頁面。

如果你正在準備第一次上架，[做免費診斷](https://devoria.fr/zh-hant/diagnostic)：它會告訴你先從哪一步著手，並寄給你我的 Apple 防退件檢查清單。

沒有人能保證 Apple 會接受你的 App。但把這五個機制做好、做得明顯，至少能把這個退件原因從清單上劃掉。

## 常見問題

### 「Guideline 1.2 - Safety - User-Generated Content」是什麼意思？

這是 Apple 退件訊息中的標題。意思是你的 App 顯示了使用者建立的內容，卻沒有具備所有預期的保護：過濾、快速處理的檢舉、封鎖、公開聯絡方式，以及已同意的使用條款。

### 排行榜上的暱稱算是使用者內容嗎？

Apple 的條文沒有明說。我把它當成使用者內容，因為暱稱是自由選擇的，而且其他玩家看得到。在 TradaZen，排行榜上的暱稱會經過過濾、可以被檢舉，有問題時會換成中性暱稱。

### 真的要在 24 小時內處理檢舉嗎？

Apple 的退件訊息就是這樣要求的。規定條文則是寫快速回應。所以光有自動過濾不夠：要有人移除內容並把發布者停權。在那之前，多次檢舉後的自動隱藏能幫你撐住。

### 使用條款一定要在 App 內同意嗎？

這是最保險的做法。退件訊息要求使用者同意不容忍不當內容與濫用者的條款。頁面底部的一個連結無法證明使用者同意。在第一次發布前放一個有「我同意」按鈕的畫面，就毫無疑義。

### 匿名聊天 App 能通過 guideline 1.2 嗎？

目前的條文把隨機或匿名聊天列為不適合上架 App Store 的用途。主要用於這類用途的 App，就算有過濾、檢舉和封鎖，也可能在未經通知的情況下被下架。


## 你的專案

[Review Kit](https://devoria.fr/zh-hant/kits/app-review)：我的 App Store 審查檢查清單、我被 Apple 退件後的修正、Google Play 檢查清單，以及三個 Claude Code skill。$1,749。

[iOS & Android Kit](https://devoria.fr/zh-hant/kits/ios)：用 Claude Code 打造你的 iPhone 和 Android App：我自己 App 的起始程式碼、上架商店的完整流程，以及所有套件。$3,599。

[診斷：你離自己的 iPhone App 還差什麼](https://devoria.fr/zh-hant/diagnostic)：7 個問題，60 秒：找出真正卡住你發布 iPhone App 的原因，拿到你的 4 步驟路線，以及最適合你的套件。
