App Store 的社群媒體勾選欄,以及它的代價
App Store Connect API 裡的兩個布林欄位,撐起了 2026年9月開始生效的整套送審要求:socialMedia 與 socialMediaAgeRestricted。1 其中第二個的代價,是一項 entitlement、一次 API 導入,以及 app 內部的一段行為分支。
Apple 在 2026年6月8日公布這項要求:「自 2026年9月起,若要向 App Store 送出新版本或更新,或為替代 app 市集的散布進行公證,您將必須聲明您的 app 或遊戲是否包含社群媒體功能。」2 7月9日,Apple 讓問卷更動正式上線,並補上一句話,決定了在那之前這段時間該怎麼用:「即日起即可檢視並回答這些問題。」3
重點摘要
- 這項聲明現在就已經在 App Store Connect 上線,2026年9月起才成為強制項目。「可以填」到「必須填」之間的這段空檔,是留給您做決定的,不是留給您趕死線的。23
- Apple 的確定義了「社群媒體功能」,而且定義了四次,彼此對不上。6月版把範圍框在「會把內容明顯散播給許多使用者」的動態消息;7月版則整句拿掉。234
- App Store Connect API 把答案以兩個可寫入的布林值對外提供,同時把
userGeneratedContent與messagingAndChat保留為各自獨立的問題,各有各的分級下限。社群媒體是一條新的軸線,不是換個名字而已。14 - 想讓 app 不落進 13 歲以下的社群媒體分類,要滿足的是三個條件,不是一個。Apple 的新聞稿只點名 Declared Age Range API;App Store Connect 說明文件還加上兩件事:13 歲以下使用者完全不得使用,而且「僅遞送適齡的 UGC」。24
- Declared Age Range API 只出現在 iOS、iPadOS、Mac Catalyst 與 macOS 上,其餘平台一概沒有。5 tvOS、visionOS 或 watchOS 的 app 在 9月一樣得回答這個問題,但文件上唯一能取得豁免資格的做法,在它的平台上根本不存在。
這個週期裡,唯一由日曆觸發的變更
這個週期我寫過的其他破壞性變更,都在等您先動手。啟動畫面要求要等到您改用 iOS 27.0 SDK 建置才觸發。@State 巨集要等到您用 Xcode 27 打開專案才觸發。On Demand Resources 的棄用只會丟出一個編譯器警告,您想無限期忽略也行。工具鏈按兵不動,這些就一個也追不到您身上。
社群媒體聲明卻躲不掉,因為 Apple 把它綁在一個月份上,也綁在一件您本來就會做的事情上。一行程式碼的錯誤修正,走的是跟功能改版一模一樣的送審流程;到了 9月,這條流程就會開口問您。
適用範圍很窄,值得逐字讀清楚。這項要求涵蓋的是「向 App Store 送出新版本或更新」以及「為替代 app 市集的散布進行公證」。2 7月的公告重述為「向 App Store 送出新 app 或更新」與「送交 app 以進行替代散布的公證」。3 兩份公告都沒提到 SDK 版本、部署目標,或任何平台。已經上架的 app 照賣不誤。這道關卡只守在下一次送審的門口。
您的答案換來的代價,是被歸進某個家長可以設上限的分類。Time Allowances 今年秋天登場,同行的還有 Ask to Browse、Schedules,以及重新設計的「螢幕使用時間」,讓家長「以更有彈性的方式管理孩子花在各類 app 上的時間,包括娛樂、遊戲與社群媒體」,並以依年齡量身訂做的建議作為起點。16 娛樂與遊戲的歸類跟著您在 App Store Connect 選的類別走。社群媒體的歸類則只跟著問卷答案走,「無論在 App Store Connect 中選擇了什麼類別」。2 一款附帶動態消息的解謎遊戲,會落進家長最先勒緊的那個分類,產品頁上寫什麼都一樣。
Apple 有定義這個詞,而定義會漂移
碰到政策題,最常見的失敗方式是憑空猜一個沒人定義過的字。Apple 公布了定義,猜測空間因此縮小;但它公布了四次,邊界各不相同。
6月的寫法是舉例式的:「這包括透過社群動態消息或類似的探索機制,重新散布、放大使用者生成內容,或與之互動,並將內容明顯散播給許多使用者的能力。」2
7月的寫法是定義式的,也更短:「社群媒體功能定義為:透過社群動態消息或類似的探索機制,重新散布、放大使用者生成內容,或與之互動的能力。」3 那句「明顯散播給許多使用者」的限定語不見了。
App Store Connect 說明文件版本最長,保留了限定語,還補上例子:「透過社群動態消息或類似的探索機制,重新散布、放大使用者生成內容或與之互動,並將內容明顯散播給許多使用者。可能包括:使用者透過社群動態消息、社群、搜尋或其他分享與探索工具,轉發、按讚、留言、做出反應,或讓使用者生成內容更容易被看見。」4
四處定義裡有三處要求「廣泛且可見的擴散」。有一處沒有;而對一個剛好卡在邊界上的 app 來說,這個差別就決定了答案。我會把說明文件那一頁當作準據,因為問卷本身會連到那一頁,而新聞稿終究會過時;不過這樣讀是我的判讀,不是 Apple 的指示。「可能包括」這四個字也重要:Apple 列的是例子,並沒有把集合封死,所以一項功能就算跟那五個動詞都不像,仍然可能被認定符合。
真正讓邊界清楚起來的,是這個描述標籤旁邊站著誰。Apple 另外單獨定義了「使用者生成內容」,指「將使用者建立的內容廣泛散布,並作為 app 預期使用者體驗的一環」;也單獨定義了「訊息與聊天」,指使用者「可透過 app 內的功能彼此直接溝通」。4 App Store Connect API 原封不動保留了這個切分,把 userGeneratedContent、messagingAndChat 與 socialMedia 當成三個彼此獨立的布林值。1
分級上的分野同樣鮮明。使用者生成內容與訊息功能都出現在 Apple 的 4+ 定義裡。社群媒體最低只出現在 13+。4 一個 app 可以容納使用者內容、可以讓人互傳訊息,仍然拿 4+;但只要加上一則會把同樣內容放大給陌生人的動態消息,下限就往上跳九歲。兩個社群媒體描述標籤都只存在於 OS 26 以後的分級架構中;Apple 給更早 OS 版本的表格裡,任何分級都找不到社群媒體這一項。4
這個欄位今天就能回答
有三份 Apple 的資料佐證問卷更動已經上線,而這正是整篇文章最實際的一點。
Apple 7月9日的公告說,問卷「現在包含關於您 app 社群媒體功能的問題」,並邀請您立刻作答。3 App Store Connect API 把 socialMedia 記載為「表示 app 是否包含社群媒體功能的布林值」,把 socialMediaAgeRestricted 記載為「表示 app 的社群媒體功能是否受年齡限制的布林值」。1 Apple 公開的 OpenAPI 規格也把兩者列為可寫入、可為 null 的布林值。1 它們就緊挨著 ageAssurance——那是 Apple 更早一輪問卷改版加進來的欄位,其定義把「declared age range API」點名為符合資格的機制之一。415 換句話說,採用豁免條款也會把您送進那個定義裡;在我看來,這是另一道需要回頭重新檢視的題目,而不是可以放著不管的東西。
打算把送審自動化的人,現在就該把形狀記熟:用 GET /v1/appInfos/{id}/ageRatingDeclaration 讀取聲明,用 PATCH /v1/ageRatingDeclarations/{id} 寫入,兩個布林值都可以傳給 fields[ageRatingDeclarations] 參數。1 一條手工拼裝年齡分級 payload 的自動化管線,會一路順利跑到它不順利的那天為止。
還有一項後果只在 7月才浮上檯面:「具備這些功能的 app,其 App Store 產品頁上會顯示新的『社群媒體』內容描述標籤。」3 答「是」改變的不只是家長控制的分類,還有您的商店頁面。
所以,這禮拜就把問卷打開,看看 App Store Connect 算出來的分級是什麼。這麼做在您送審之前不構成任何承諾,卻能把一條死線變成一個您早就做完的決定。
豁免條款有三個條件,不是一個
Apple 的新聞稿把 13 歲以下這條路寫得像是一次 API 呼叫就能搞定:「如果您聲明 app 或遊戲包含社群媒體功能,但這些功能對 13 歲以下的任何人都停用,該 app 便不會被納入 13 歲以下使用者的社群媒體 Time Allowance 分類……您也必須(至少)使用 Declared Age Range API 來檢查使用者的年齡範圍。」2
App Store Connect 說明文件把同一個描述標籤寫成三項要求:「13 歲以下使用者無法使用社群媒體功能。在啟用社群媒體功能之前,至少會呼叫 Declared Age Range API 以檢查使用者的年齡範圍。僅遞送適齡的 UGC。」4
第三句話沒人引用。「僅遞送適齡的 UGC」是一項內容審核義務,背後沒有對應的 API,沒有公布的門檻,也沒有任何您跑得出來的測試。Apple 既沒有定義什麼叫「適齡」,也沒有定義遞送機制。一個團隊就算裝好年齡關卡,卻把同一份未經過濾的動態消息端給 12 歲的孩子,按照說明文件自己的文字,三個條件只達成了一個。
也請留意豁免條款買不到什麼。Apple 自己的句子接著寫道,這類 app「對 13 歲以上的使用者仍會留在社群媒體分類中」。2 豁免只涵蓋 13 歲以下的使用者,所以一個 14 歲的孩子,照樣受家長為社群媒體設下的任何上限所限。
分級表格裡有一處矛盾,我沒能解開。Apple 的新聞稿說,選了受限選項之後,分級仍由您「在年齡分級問卷中的整體回答」決定,而且「可能得出低於 13+ 的分級」。2 但 Apple 的全球表格把「社群媒體」與「對 13 歲以下使用者停用的社群媒體」兩者都列在 13+ 的「功能」項下;各地區表格則把兩者一起放在澳洲 16+、巴西 A16、韓國 15+、越南 16+。4 若照其他每一列的讀法——描述標籤設下一個下限——受限選項看起來同樣是 13+ 的下限。Apple 沒有調和這兩者,我也不打算去猜分級計算器實作的是哪一份文件。到上線的問卷裡選那個選項,讀出算出來的分級,然後相信計算器勝過相信這兩份文件。
順著這個勾選欄一路追進 app 裡
假設您決定走豁免這條路。您在 Xcode 的 target 上啟用 Declared Age Range 能力,這會加上 com.apple.developer.declared-age-range entitlement:「表示您的 app 是否可以請求某人年齡範圍的布林值。」6 接著您帶著自己在意的門檻呼叫 API,在 SwiftUI 裡它以環境動作的形式出現:5
Apple 對這個動作附了一條擺放規則:要「回應使用者互動」時才使用,而 Apple 自己的範例把呼叫放在按鈕之後。5 這個請求可能會顯示一張系統表單,所以從 .task 或 onAppear 觸發,等於是把權限提示丟給一個什麼都還沒要求的人。請改把它掛在「進入受管制介面」的那一次點擊上。
import SwiftUI
import DeclaredAgeRange
@available(iOS 26.0, *)
struct SocialFeedGate: View {
@Environment(\.requestAgeRange) private var requestAgeRange
@State private var feedEnabled = false
@State private var checking = false
var body: some View {
if feedEnabled {
FeedView()
} else {
Button("Open community feed") {
checking = true
Task {
feedEnabled = await resolveGate()
checking = false
}
}
.disabled(checking)
}
}
private func resolveGate() async -> Bool {
guard let response = try? await requestAgeRange(ageGates: 13) else {
return false // AgeRangeService.Error: your default, not Apple's
}
guard case let .sharing(ageRange) = response else {
return false // .declinedSharing
}
guard let lowerBound = ageRange.lowerBound else {
return false // nil lower bound means below your lowest gate
}
return lowerBound >= 13
}
}
這段程式碼裡有四個細節,決定這道關卡守不守得住。
您最多只有三個門檻。 兩個多載都停在三個門檻:SwiftUI 動作是 callAsFunction(ageGates threshold1: Int, _ threshold2: Int? = nil, _ threshold3: Int? = nil),UIKit 方法只多了呈現用的錨點。7 四個區間就是天花板。光是 Apple 規則要的 13、澳洲法律要的 16,還沒開始設計任何東西,四個區間就已經用掉三個。
下限為 nil 是答案,不是錯誤。 AgeRange.lowerBound 與 upperBound 都是 Int?,而 Apple 把 nil 的意思講得很白:「當此值為 nil 時,表示該人的年齡範圍低於您指定的最低年齡,也就是未達您的最低年齡要求。」8 樂觀解包的程式碼,會正好在這道關卡本該保護的那群人身上,把判斷整個反過來。
拒絕是一條真實的分支,而 Apple 沒說該怎麼處理。 AgeRangeService.Response 帶著 .sharing(range:) 與 .declinedSharing 兩種情況。9 在某些受管制地區,「系統會自動提供該人的年齡範圍」,使用者「無法拒絕分享」;在非管制地區,「如果該人拒絕,您會收到 declinedSharing 回應」。10 一次拒絕,和一位重視隱私的成年人長得一模一樣:當成 13 歲以下處理,您擋住了大人;當成成年人處理,您打開了那道自己承諾要關上的門。Apple 把預設值留給您決定。我會選擇預設關閉(fail closed),並在介面上把這件事講明白。
您設的門檻只是建議。 系統「可能會根據該人的所在地與適用法規,回傳覆寫您所指定年齡門檻的年齡範圍」;而當當地法規要求特定門檻時,「回傳的年齡範圍反映的是法規要求,而非您年齡門檻的邊界」。7 假設回傳邊界等於請求邊界的程式碼,會在最嚴格的司法管轄區裡最先出包。
還有一個行為屬於設計層面,我預期它會製造客服工單。Apple 會快取答案:「當某人的年齡跨進新的範圍時(例如滿 13 歲),API 仍會持續回傳先前的範圍,直到其原始聲明的週年日為止。」10 一個週一滿 13 歲的孩子,可能好幾個月都還被讀成 13 歲以下。補救方式是一條使用者得自己走完的「設定」路徑:進入自己的名字,接著「個人資訊」,再進入「App 的年齡範圍」。10 任何以 13 歲為關卡的 app,都得把這串指示寫進自己的 UI,否則沒有人找得到。
另外兩個較小的細節在設計階段就會影響決策。isEligibleForAgeFeatures 會回報使用者是否位於要求年齡驗證的地區;而在 macOS 上,它「會回傳 false,因為系統並不要求對該人或該裝置進行年齡驗證」,所以 Mac app 直接呼叫 requestAgeRange 就好。11 至於用來回報年齡如何被設定的 AgeRangeDeclaration,本身已經翻修過一輪:26.2 時是六個細分的 case,分別點名付款方式、政府核發證件,以及本人與監護人的其他驗證方法;到了 26.5 全部收斂成單一的 confirmed。12 想問某位使用者是用哪種方法驗證的?現在的 API 已經不再回答。
再來是平台門檻——這件事只有可用性中繼資料說了,沒有任何一份文字敘述提到。Declared Age Range 公布的是 iOS 26.0、iPadOS 26.0、Mac Catalyst 26.0 與 macOS 26.0,此外什麼都沒有:沒有 tvOS,沒有 visionOS,沒有 watchOS。5 Time Allowances 落在同一批平台上,「iOS 27、iPadOS 27 與 macOS 27 或更新版本」;而聲明要求本身完全沒有平台限定語。23 因此,一個帶有社群動態消息的 tvOS 或 visionOS app,9月照樣得回答,卻無法達成豁免條款文件上寫明的最低要求,因為它所點名的 API 在那裡根本不存在。把這個落差讀成疏漏、而非刻意的例外,是我的判讀;Apple 兩邊都沒有說法。
我自己的八個 app 會怎麼填
在評論別人的程式碼之前,我先把自己的盤點做完:八個 Xcode 專案,491 個 Swift 檔案。13 沒有任何一個含有 CKShare、UICloudSharingController、共享或公開的 CloudKit 資料庫、GameKit,或任何 Declared Age Range 的符號。這批 app 裡沒有一個會把內容從一個人搬到另一個人手上。四個專案完全沒有任何可疑介面。另外四個有些介面會讓謹慎的人猶豫一下,而它們分成三類,值得攤開來想清楚。
Get Bananas 有一份共享購物清單,而「共享」比字面上窄得多。 這個 app 把一份 JSON 文件寫進 iCloud ubiquity 容器,再從 iPhone、Apple Watch 與 Mac 讀回來;com.apple.developer.icloud-services 設為 CloudDocuments,整個專案裡沒有任何 CloudKit 共享。13 清單是在同一個人的多台裝置之間共享,不是在人與人之間,所以沒有任何東西被重新散布,也沒有第二個使用者可以散播給。等我為了家庭協作加上 CKShare 的那天,答案才會翻轉;而即使翻轉,翻到的也是使用者生成內容,不是社群媒體,因為一份兩個人的採買清單既沒有動態消息,也沒有探索介面。真正要盯的那條線在更外面:共享清單,加上一個公開的範本庫,再加上按讚,那就是拐了幾個彎的動態消息。
三個 app 會叫出分享表單,而分享表單不是社群功能。 Get Bananas、Water 與 ResumeGeni 的 iOS app 各自包了一層 UIActivityViewController,把使用者自己的內容交給他們挑選的任何 app。13 內容前往「訊息」或「郵件」之後就一去不回,不會落回任何由我的 app 控制的介面;而 Apple 的定義關鍵在於「透過社群動態消息或類似的探索機制」進行的重新散布,系統分享表單不是那種東西。4 這個推論涵蓋了 App Store 相當大的一片:匯出不等於發布。
Watch Connectivity 看起來像訊息功能,其實不是。 Get Bananas 與 Reps 都用了 WCSession,它在手機與配對給同一個人的手錶之間搬資料;而 Apple 的「訊息與聊天」描述標籤要求的是「使用者可彼此直接溝通」。413 這裡兩端坐的是同一位使用者。
這個「零命中」的結果可以推廣,而那才是值得借走的部分。這批 app 每一個都只為內容的作者保存內容,再把它顯示給同一個人看。問卷問的完全是另一件事:您的 app 會不會把某個人的內容,透過某種會擴散的機制,放到別人眼前。追蹤器、計時器與學習工具答「否」,靠的是架構,不是政策解讀。真正需要動腦的,是那些帶有「使用者看得見彼此作品」介面的 app。
另一個該優先確認的數字是部署目標。七個有 iOS target 的專案裡,有六個落在 iOS 26.0 以上;Ace Citizenship 的部分 target 仍宣告 17.0 與 17.5。13 低於 26.0 的一律叫不到這個 API,等於豁免路線直接消失,只剩下單純聲明這一個誠實的答案。
平台落差在同一份盤點裡也現形,而且比版本問題涵蓋得更廣。八個專案裡有四個在 SUPPORTED_PLATFORMS 中宣告了 xros xrsimulator:Reps、Return、Water 與 Yawara。Reps 另外加上 appletvos appletvsimulator,並附一個獨立的 watchos watchsimulator target;Return 與 Banana List 也帶著 watchOS target。13 Declared Age Range 公布的可用性只有 iOS 26.0、iPadOS 26.0、Mac Catalyst 26.0 與 macOS 26.0,tvOS、visionOS、watchOS 一列都沒有。5 上述每一個 target 都欠 9月那份聲明;而在其中任何一個上面,答「是」都會讓豁免條款遙不可及,因為豁免條款仰賴的 API 並未在那些平台上推出。
關於方法要提醒一句,因為我第一次就搞錯了。XROS_DEPLOYMENT_TARGET 會出現在根本沒有 visionOS 目的地的專案裡,因為 Xcode 一律會把這個設定寫進各個建置組態。ResumeGeni 帶著 XROS_DEPLOYMENT_TARGET = 26.2,卻只建置 iphoneos iphonesimulator。13 請讀 SUPPORTED_PLATFORMS,而不是部署目標的鍵值,否則您會數進自己根本沒出貨的平台。
答案不再只是技術問題的那條線
Apple 在 Declared Age Range 文件上附了一段免責聲明,值得讀兩遍:這些資料「係基於終端使用者,或其父母或監護人所聲明的資訊」,而且「您必須自行負責確保遵守可能適用於您 app 的相關法律或法規」。14
這句話畫出了本文停下來的那條線。Apple 的問卷產出一個分級和一個 Time Allowance 分類,唯獨產不出合規。自 2025年12月10日起,澳洲法律已要求特定社群媒體平台阻止 16 歲以下的人擁有帳號;而 Apple 針對該法的指引,把 Declared Age Range API 列為五項工具之一。15 問卷與法條重疊卻不對齊:一邊問 13 歲,另一邊問 16 歲,而您手上只有三個門檻要同時兼顧兩者。
您的 app 在某個法域下是不是社群媒體平台,這題要問那個法域的律師。它在 Apple 問卷下有沒有社群媒體功能,這題是您的,而且今天就能對照 Apple 公布的定義回答。
常見問題
社群媒體那題現在已經在 App Store Connect 上線了嗎?
是的。Apple 2026年7月9日的公告指出,問卷「現在包含關於您 app 社群媒體功能的問題」,且「即日起即可檢視並回答這些問題」。3 App Store Connect API 也獨立佐證了這一點,把 socialMedia 與 socialMediaAgeRestricted 記載為 AgeRatingDeclaration 資源的屬性,兩者都可透過 PATCH /v1/ageRatingDeclarations/{id} 寫入。1 現在作答不構成任何承諾:回答在您送審時才生效,而 2026年9月是「不填就送不出去」的起點。2
Apple 有定義「社群媒體功能」嗎?
有,在四個地方,含兩種不同範圍。App Store Connect 說明文件給的版本最完整,要求「透過社群動態消息或類似的探索機制,重新散布、放大使用者生成內容或與之互動,並將內容明顯散播給許多使用者」,接著把轉發、按讚、留言、做出反應與提高能見度列為例子。4 6月版帶著同樣的範圍限定語;7月版把它拿掉。23 由於那些例子屬於舉例而非窮舉,分類自己的 app 這件事仍然落在您身上;而我會照說明文件那一頁來分類。
我的 app 有使用者生成內容,這就自動算社群媒體嗎?
不算。Apple 把兩者維持成不同的問題,各有定義,也各有分級後果。「使用者生成內容」涵蓋「將使用者建立的內容廣泛散布,並作為 app 預期使用者體驗的一環」,並出現在 Apple 的 4+ 定義裡。4 社群媒體則要求透過動態消息或同等的探索介面進行重新散布、放大或互動,最低出現在 13+。4 API 以彼此獨立的 userGeneratedContent 與 socialMedia 布林值忠實反映了這個切分。1 而一個「使用者建立的內容只有自己看得到」的 app,兩者都不是。
13 歲以下那個選項,實際上要求我做出什麼?
三件事,而且只有第二件是 API。App Store Connect 說明文件要求:13 歲以下使用者不得使用社群媒體功能;「在啟用社群媒體功能之前,至少會呼叫 Declared Age Range API 以檢查使用者的年齡範圍」;以及「僅遞送適齡的 UGC」。4 所以您要加上 com.apple.developer.declared-age-range entitlement,在任何社群介面出現之前,帶著含 13 的門檻呼叫 requestAgeRange,針對回應分支處理——包括 Apple 沒有定義的那個拒絕情況——並且另外確保您遞送給未成年人的內容是適齡的。56 這個 API 把您限制在三個門檻內,還會把某人的年齡範圍快取到其聲明的週年日為止,所以一位剛滿 13 歲的使用者,在更新「設定」之前都會被繼續讀成更小。710
重點整理
給 iOS 開發者:
- 這禮拜就把問卷答完,別等到 9月。欄位已經上線,回答只在送審時才生效,而讀出算好的分級,能解決兩份公告都沒講乾淨的 13+ 問題。34
- 如果您要走 13 歲以下的豁免路線,請按三個條件編列成本,而不是一次 API 呼叫;並且刻意把拒絕分支寫清楚。.declinedSharing 和一位重視隱私的成年人長得一模一樣,而 Apple 沒有公布該往哪一邊倒的指引。49
給 tvOS、visionOS 或 watchOS 團隊: - 動手規劃之前先查可用性。Declared Age Range 只公布 iOS、iPadOS、Mac Catalyst 與 macOS,此外一列都沒有;也就是說,豁免條款文件上的最低要求在您的平台上無法達成,但 9月那份聲明照樣適用於您的送審。25 - 同一個落差也會基於另一個理由,波及任何低於 iOS 26.0 的 target:沒有 API,就沒有豁免,只剩下單純聲明這個唯一誠實的答案。5
給發版負責人:
- 把日期本身當成觸發條件,這一點跟這個週期的其他變更都不一樣。啟動畫面鍵值與 @State 巨集是由您掌控的 SDK 和工具鏈觸發;9月觸發的,是您本來就要做的那次送審。2
- 讓答案先經過負責產品頁的人。聲明具備社群媒體功能,會在您的 App Store 頁面加上一個「社群媒體」內容描述標籤,而這項後果 Apple 直到 7月才揭露。3
27 週期持續按照「什麼東西按下開關」來分類自己的變更:一個建置設定、一條工具鏈、一個編譯器警告,現在再加上一本日曆。同一個週期裡牙齒最軟、身後遷移工作卻最大的那項棄用,請見 On Demand Resources 與 Background Assets 的代價。完整系列請見 Apple 生態系系列。
參考資料
-
Apple,AgeRatingDeclaration.Attributes,App Store Connect API。以下內容的出處:”A Boolean value that indicates whether the app includes social media features”(
socialMedia)、”A Boolean value that indicates whether the app’s social media features are age restricted”(socialMediaAgeRestricted)、”A Boolean value that indicates whether the app uses age assurance to verify a person’s age”(ageAssurance),以及各自獨立的userGeneratedContent與messagingAndChat屬性。端點路徑、可寫入性與 sparse fieldset 值,係對照 Apple 公布的 App Store Connect OpenAPI specification 查核,版本 4.4.1,於 2026年7月25日下載,封存時間戳為 2026年7月15日:AgeRatingDeclaration帶有 29 個屬性,AgeRatingDeclarationUpdateRequest將全部 29 個都開放為可為 null 的可寫入欄位,包含socialMedia、socialMediaAgeRestricted與ageAssurance,路徑則為GET /v1/appInfos/{id}/ageRatingDeclaration與PATCH /v1/ageRatingDeclarations/{id}。 ↩↩↩↩↩↩↩↩ -
Apple,Introducing Time Allowances,Apple Developer News,2026年6月8日。以下內容的出處:9月的要求(”Starting September 2026, you’ll be required to indicate whether your app or game includes social media capabilities in order to submit new versions or updates to the App Store, or for notarization for distribution on alternative app marketplaces”)、平台清單(”New Time Allowances in iOS 27, iPadOS 27, and macOS 27, or later”)、6月版定義(”This includes the ability to redistribute, amplify, or interact with user-generated content through a social feed or similar discovery method that visibly spreads content to many users”)、問卷更動的預告(”Starting July 2026, the age rating questionnaire will be updated to let you indicate whether your app or game includes social media capabilities”)、單純聲明的 13+ 下限,以及受限選項的相關敘述,包括 “You’ll also need to use the Declared Age Range API (at a minimum) to check users’ age ranges” 與 “If you select this option, your overall responses in the age rating questionnaire determine your age rating and may result in a rating lower than 13+.”。同時也是 “Time Allowance categories are different from categories for user discovery on the App Store.” 的出處。2026年7月25日對照該頁面 HTML 逐字查核。 ↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩
-
Apple,Age rating questionnaire now includes social media questions,Apple Developer News,2026年7月9日。以下內容的出處:問卷更動已上線(”the age rating questionnaire in App Store Connect now includes questions about your app’s social media capabilities”)、縮短後的定義(”A social media capability is defined as the ability to redistribute, amplify, or interact with user-generated content through a social feed or similar discovery method”)、產品頁後果(”Apps with these capabilities will display a new Social Media content descriptor on their App Store product page”)、可用性聲明(”You can review and answer these questions starting today”),以及重申的 9月適用範圍(”beginning in September 2026, responses will be required when submitting new apps or updates to the App Store, or when submitting apps for notarization for alternative distribution”)。2026年7月25日對照該頁面 HTML 逐字查核。同日搜尋 Apple Developer News,關於 Time Allowances、年齡分級或社群媒體聲明,沒有比這一則更新的項目。 ↩↩↩↩↩↩↩↩↩↩↩↩
-
Apple,Age ratings values and definitions,App Store Connect Help。本文所引用的「功能」定義出處,涵蓋 Social Media、Social Media Disabled for Users Under 13(”Users under 13 don’t have access to social media capabilities. At a minimum, the Declared Age Range API is called to check users’ age ranges before enabling social media features. Only age-appropriate UGC is delivered”)、User-Generated Content 與 Messaging and Chat,以及 In-App Controls 中 Age Assurance 的定義。同時也是各分級表格的出處,這些表格全部適用於至少執行 iOS 26、iPadOS 26、macOS Tahoe 26、tvOS 26、visionOS 26 與 watchOS 26 的裝置。在 “Age rating values” 標題底下,Apple 的全球表格把 User-generated content、Messaging and chat、Advertising、Parental controls 與 Age assurance 列於 4+,並把 Social media 與 Social media disabled for users under 13 兩者都列在 13+ 的 Capabilities 之下。四份地區表格則把兩個社群媒體描述標籤一起放在 “Australia age rating values” 的 16+、”Brazil age rating values” 的 A16、”Republic of Korea age rating values” 的 15+,以及 “Vietnam age rating values” 的 16+。另有一節 “Age ratings on OS versions earlier than 26”,其中任何分級都沒有社群媒體描述標籤。2026年7月25日自該頁面 HTML 讀取。 ↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩
-
Apple,Declared Age Range,框架文件。可用性:iOS 26.0、iPadOS 26.0、Mac Catalyst 26.0 與 macOS 26.0,沒有 tvOS、visionOS 或 watchOS 的欄位。框架概述(”Use the Declared Age Range API to request that people share their age range with your app”)與家人共享行為的出處:父母、監護人或家庭群組管理人可以 “always share a child’s age information with your app, ask the child every time, or never share their age information”。SwiftUI 環境動作記載於 DeclaredAgeRangeAction;本文程式碼範例中的
@Environment(\.requestAgeRange)用法出自 Apple 自己在 AgeRangeService 上的範例。可用性於 2026年7月25日自 Apple 文件的 JSON 讀取,因為 HTML 是透過 JavaScript 渲染的。 ↩↩↩↩↩↩↩↩ -
Apple,com.apple.developer.declared-age-range,Entitlements 參考文件。”A Boolean value indicating whether your app may request a person’s age range.” 可用性:iOS 26.0、iPadOS 26.0 與 macOS 26.0。Apple 的指示是「在 Xcode 中於您的 target 上啟用 Declared Age Range 能力」來加入它。請注意,entitlement 頁面沒有列出 Mac Catalyst,框架頁面卻有;這個不一致出在 Apple 自己的中繼資料,我沒有實測哪一份才算準。 ↩↩
-
Apple,
DeclaredAgeRangeAction上的 callAsFunction(ageGates:::),以及AgeRangeService上的 requestAgeRange(ageGates:::in:),Declared Age Range。SwiftUI 動作宣告為func callAsFunction(ageGates threshold1: Int, _ threshold2: Int? = nil, _ threshold3: Int? = nil) async throws -> AgeRangeService.Response;UIKit 方法宣告同樣的三個門檻,外加in viewController: UIViewController。兩者的上限都是三個門檻。UIKit 頁面同時是地區覆寫規則的出處:”The system may return age ranges that override the age gates you specify based on the person’s location and applicable regulations. When local regulations require specific age gates, the returned age range reflects regulatory requirements rather than the bounds of your age gates.” 該動作可用於 iOS 26.0、iPadOS 26.0、Mac Catalyst 26.0 與 macOS 26.0;帶in viewController:的多載列出 iOS 26.0、iPadOS 26.0 與 Mac Catalyst 26.0,macOS 則由NSWindow版本負責。 ↩↩↩ -
Apple,AgeRangeService.AgeRange 與 lowerBound,Declared Age Range。隱私框架說明(”Rather than receiving an exact age, you receive age range bounds that correspond to your specified age gates”)、屬性宣告
var lowerBound: Int?與var upperBound: Int?(皆自 iOS 26.0 導入),以及本文引用的 nil 語義出處:”When this value isnil, the person’s age range is below your lowest specified age, indicating they are under your minimum age requirement. When the value is present, it represents the lowest age that the person meets or exceeds.” Apple 在同一頁的實例:年齡門檻設為 13、16、18 時,lowerBound為 16 表示該人至少 16 歲,”but may or may not be18or older”。這個結構另外提供ageRangeDeclaration與activeParentalControls。 ↩ -
Apple,AgeRangeService.Response,Declared Age Range。兩種情況:
sharing(range:),”Contains the person’s shared age range information”;以及declinedSharing,”Indicates the person declined to share their age range with your app”。當使用者拒絕時,app 應該預設倒向哪一邊,Apple 沒有給任何指引;預設關閉並在介面中揭露該行為,是我的建議。 ↩↩ -
Apple,Requesting people’s age range information in your app,Declared Age Range。以下內容的出處:快取行為(”The system protects privacy by caching age range responses. When a person’s age crosses into a new range (for example, when they turn 13), the API continues returning the previous range until the anniversary of their original declaration”)、「設定」補救路徑(iPhone 或 iPad 上的「設定」,或 Mac 上的「系統設定」,接著點自己的名字,再進入「個人資訊」,然後是「App 的年齡範圍」)、受管制地區的行為(”the system automatically provides the person’s age range”,且使用者 “can’t decline sharing”),以及非管制地區的行為(”If the person declines, you receive a
declinedSharingresponse”)。 ↩↩↩↩ -
Apple,isEligibleForAgeFeatures,Declared Age Range。
var isEligibleForAgeFeatures: Bool { get async throws },自 iOS 26.2、iPadOS 26.2、Mac Catalyst 26.2 與 macOS 26.2 起提供。以下內容的出處:”In macOS,isEligibleForAgeFeaturesreturnsfalsebecause the system doesn’t require Age Assurance for the person or device. However, you can still callrequestAgeRangein macOS to get the declared age range.” ↩ -
Apple,AgeRangeService.AgeRangeDeclaration,Declared Age Range。現行 case:
selfDeclared與guardianDeclared(iOS 26.0),以及confirmed(iOS 26.5),最後一個描述為 “Indicates a user’s age range was set using a scrutinized method, like a credit card or government ID”。Apple 文件把另外六個 case 收在 Deprecated 標題底下:paymentChecked、governmentIDChecked、checkedByOtherMethod,以及三個對應的監護人版本,皆自 iOS 26.2 導入。可用性於 2026年7月25日自 Apple 文件的 JSON 讀取;各個 case 的頁面在平台中繼資料中都沒有deprecatedAt版本,因此這項棄用是由文件自身的分組陳述的,而不是由可用性註記。 ↩ -
作者於 2026年7月25日,在 macOS 26.5.2 搭配 Xcode 26.6(build 17F113)上對八個 Xcode 專案所做的盤點。專案目錄位於
~/Projects,這裡精確列名是因為其中兩個很容易混淆:Banana List(上架名稱為 Get Bananas)、Reps、Return、Ace-Citizenship、Water、Yawara、Cels,以及ResumeGeniApp——後者是 SwiftUI 的 iOS app,並非放在它旁邊、只有四個檔案的獨立ResumeGeniSafari 網頁擴充功能專案。排除build、DerivedData、.build、Pods、.git與worktrees後的 Swift 檔案數依序為 55、77、57、26、34、143、29、70,合計 491。已對每一個 Swift 檔、entitlements 檔與 property list 搜尋CKShare、UICloudSharingController、CKAllowedSharingOptions、sharedCloudDatabase、publicCloudDatabase、GKLeaderboard、GKLocalPlayer、GKMatch、MFMessageComposeViewController、MSMessagesAppViewController、DeclaredAgeRange、AgeRangeService、requestAgeRange與declared-age-range。每個專案、每個樣式皆為零命中。UIActivityViewController出現在 Get Bananas、Water 與 ResumeGeni 的 iOS app;WCSession出現在 Get Bananas 與 Reps;ASAuthorizationAppleID只出現在 ResumeGeni 的 iOS app。Get Bananas 透過FileManager.default.url(forUbiquityContainerIdentifier:)取得的 iCloud ubiquity 容器,以 JSON 形式保存清單,entitlements 中com.apple.developer.icloud-services設為CloudDocuments,專案內任何地方都沒有 CloudKit 共享。部署目標自各專案的project.pbxproj讀取:七個專案宣告IPHONEOS_DEPLOYMENT_TARGET(Get Bananas 26.0、Reps 26.0 與 26.2、Return 26.1、Water 26.0、Yawara 26.5、ResumeGeni 的 iOS app 26.2,Ace Citizenship 則在各 target 間為 17.0、17.5 與 26.1),而 Cels 只宣告MACOSX_DEPLOYMENT_TARGET = 26.0,沒有任何 iOS target。平台值取自各專案的SUPPORTED_PLATFORMS建置設定,而非部署目標鍵值;這八個都是 Blake 已上架 App Store 的專案。 ↩↩↩↩↩↩↩ -
Apple,Declared Age Range,框架概述中的 Important 提示:”Data from the Declared Age Range API is based on information declared by an end user, or their parent or guardian, and may be confirmed using a payment method (like a credit card), government ID, or another method. You are solely responsible for ensuring compliance with associated laws or regulations that may apply to your app.” ↩
-
Apple,New Requirements for Social Media Apps in Australia,Apple Developer News,2025年12月8日。澳洲要求的出處(”Beginning December 10, 2025, a new Australian law will require certain social media platforms operating in Australia to prevent people under 16 from having a social media account”),以及 Apple 為此列出的五項工具:Declared Age Range API、App Store app 說明、產品頁上顯示的 App 內控制項(in-app controls)、自行選擇更高的最低年齡分級,以及 Age Suitability URL。Apple 表示 “Impacted developers are responsible for making sure they follow the requirements of the new law.” 同時也是把年齡驗證問題的時間點定在社群媒體問題之前的依據:”This year, Apple updated the age ratings questionnaire that is required for all apps. The update included adding new questions about in-app controls, such as the presence of age assurance and parental controls.” ↩↩
-
Apple,Apple previews new child safety features,Apple Newsroom,2026年6月8日。Time Allowances 面向使用者的描述出處,該功能與 Ask to Browse、Schedules 及重新設計的「螢幕使用時間」一同推出:”Time Allowances give parents more flexible ways to manage the time their kids spend in apps across categories, including Entertainment, Games, and Social Media. When setting Time Allowances, parents are provided with guidance, based on expert research, that’s tailored to a child’s age.” ↩