小孩說「才一下下」,到底是多久?
"Just a Little Bit": How Long Is That, Really?
為什麼要看小孩的 App 使用時間、數字怎麼用才不傷感情;還有 RestBud 這次新增「今天的使用時間」,我在 Apple 後台走的那一長串繁瑣流程,一併記在這裡。
「你玩多久了?」
「才一下下。」
每個有小孩的家,大概每天都會上演一次。有意思的是,兩邊可能都沒說謊——孩子是真心覺得才一下下,大人是真心覺得已經好久。手上沒有數字,這場對話就只能比誰比較大聲。
RestBud 之前只會「鎖」:時間到,小芽遮罩升起來,播你親手錄的那一句。但鎖得再溫柔,前提都是你知道該鎖多久。所以最近我在補另一半:數。這篇分兩部分——前半寫給爸媽,談為什麼小孩的 App 使用時間值得看、數字怎麼用才不傷感情;後半是寫給我自己(和同樣在做螢幕時間 App 的開發者)的,把這次在 Apple 後台走的那一長串繁瑣流程,一步一步記下來。
第一部分 · 給爸媽:為什麼值得看憑感覺估,通常不準
Our gut estimates are usually off
研究者很早就注意到:人憑感覺估「我用了多久」,常常對不上裝置的實際記錄。2021 年發表在《Nature Human Behaviour》的一篇統整分析,比對了 106 組「自己回報」與「裝置記錄」的使用時間,結論是兩者只有中等程度的相關,自己回報的數字很少是準的。
那是大人在估自己。估孩子的——尤其是躲在房間裡、一個下午切換好幾個 App 的孩子——大概只會更難。(這句是我的推論,不是那篇研究的結論。)
💡 所以數字的第一個用處很樸素:把「我覺得」換成「看起來是」。
來源:Parry et al. (2021), Nature Human Behaviour官方怎麼建議——以及為什麼只看幾小時不夠
What the health bodies say — and why hours alone aren't enough
WHO · 5 歲以下(2019)
WHO · children under 5 (2019)
未滿 2 歲不建議看螢幕;2~4 歲,坐著看螢幕每天不超過 1 小時,越少越好。
來源:WHO (2019), To grow up healthy, children need to sit less and play more · Guidelines on physical activity, sedentary behaviour and sleep for children under 5 years of age衛福部/國民健康署衛教
Taiwan MOHW / Health Promotion Administration
未滿 2 歲不看螢幕,2 歲以上每日不要超過 1 小時;近距離用眼每 30 分鐘,就起身活動、讓眼睛休息 10 分鐘。
來源:國民健康署「室外活動 猴塞雷(好視力)」(2016) · 衛福部「居家防疫狂用眼 Eye眼動起來」(2023)AAP · 2026 年 1 月的新聲明
AAP · the January 2026 policy statement
美國兒科醫學會把重心從「幾小時」移到品質、情境與對話,並以「5 個 C」作為家庭討論的架構:Child(這個孩子)、Content(內容)、Calm(情緒與自我調節)、Crowding out(擠掉了哪些活動)、Communication(溝通)。
來源:AAP news release (2026-01-20) · AAP releases new media recommendations (5 Cs) · AAP Policy Explained三份放在一起看很有意思:WHO 和衛福部給的是「上限」,AAP 卻提醒光看時數不夠。我的理解是——時間不是全部,但它是最容易量、最適合拿來開口的那一個。內容好不好、睡眠和運動被擠掉多少,都得先知道「今天大概玩了多久」才聊得下去。
數字是拿來開口的,不是拿來定罪的
Numbers are for opening a conversation, not passing a verdict
- 兩個人看同一份數字,就沒有「誰說了算」。
- 看規律:哪一天特別長?通常在一天的什麼時候?
- 看擠掉了什麼:玩到九點的那一天,隔天早上是不是特別難起床?
- 看完不一定要縮短:也可以挑一個時段(飯前、睡前一小時)讓螢幕整段休息——這正是 RestBud 課表在做的事,規則怎麼變成課表,見〈「再五分鐘」的拉鋸戰,我把它做成一張課表〉。
RestBud 現在會「數」了
RestBud can count now
家長區的「執行狀況紀錄」頁多了一個區塊:今天的使用時間。最上面一行是今天合計(就是下面各列加起來),下面每個納管的 App 一列,附分鐘數和相對長條(由多到少,最多列 8 個)。
- 只列你放進 RestBud 清單的 App,不是整支手機。沒放進清單的 App 不會出現,也不會被算進合計。
- 看的是今天(從凌晨 0 點到現在)。
- 長條以「用最多的那個 App」為滿格——家長要看的是「誰最多」。
- 數字由 iOS 自己統計、自己畫出來(下一節說明為什麼這點很重要)。
- 語言跟著 RestBud 自己的語言設定走,和家長頁一致。
示意圖(非實機畫面):版型照程式實作畫的,App 名稱與分鐘數是舉例。
💡 目前進度:這個區塊今天(10/5)才做出來,預計隨下一個版本更新。實機的第一眼就抓到兩個問題——合計對不上列表、語言沒跟著 App 走——都已修掉(來龍去脈在第二部分的〈踩過的雷〉);完整的實機驗收還在進行。它只能在實機上看到(模擬器沒有螢幕時間授權,畫面會是空白),我還沒拍實機截圖,所以上面那張是示意圖。
為什麼 RestBud 自己「看不到」這些數字
Why RestBud itself can't see the numbers
iOS 對螢幕時間的用量數字管得很嚴。App 想顯示精確的「今天用了幾分鐘」,正規的做法只有一條:請系統開一個專用的報表 extension:系統把用量交給它,它在沙盒裡把畫面畫好,再嵌回 App。Apple 的文件寫得很直白——這個 extension 的沙盒不准發出網路請求,也不准把敏感內容帶出 extension 自己的記憶體範圍;而 App 本身「不能直接取得」這些活動資料。
換句話說:RestBud 讀不到、存不了、傳不出去。「不收集任何資料」這句話,加上統計之後依然成立。代價是這些數字也不能拿去做別的——不能存成週報、不能發通知、不能拿來觸發鎖定。
iOS 26.4 之後,Apple 另外開了一條讓 App 讀原始數字的通道,但官方文件寫明:只有在歐盟、且 Apple 帳號也屬於歐盟的裝置上才會啟用。台灣用不到,所以我也沒有往那條路設計。
來源:Apple · DeviceActivityReport · Apple · AuthorizationStatus.approvedWithDataAccess老實說:這版做不到的事
Honestly: what this version can't do
- 只有今天。沒有週報、趨勢圖——因為數字存不下來。
- 只列納管中的 App,而且只有家長區看得到。
- 數字由 iOS 統計。我的驗收標準是「跟設定 → 螢幕使用時間同一個量級,差幾分鐘可以接受」,不保證逐分鐘一模一樣。
- RestBud 另一個新功能「每日上限」顯示的「約 X 分」仍是估算;兩者並存,誰也不取代誰。
為了顯示幾個數字,要多一個 target、一個 App ID
A few numbers on screen cost one more target and one more App ID
原因是:Screen Time 的每個 extension 在 iOS 眼裡都是獨立的小 App——有自己的 Bundle ID、自己的 capability、自己的 provisioning profile。RestBud 現在有四個,彼此靠同一個 App Group(group.app.rexcode.restbud)串起來:
-
主 app ·
app.rexcode.restbud— 要授權、挑 App、排程,並把報表嵌進畫面 -
Monitor ·
….monitor— 排程到點或用量過門檻時被系統喚醒,改遮罩、發通知 -
Shield UI ·
….shieldui— 決定被鎖 App 的遮罩長相 -
Report ·
….report(這次新增)— 系統把用量交給它,它畫成畫面
一句話版:後台建 App ID、勾 Family Controls、指定 App Group、存檔;專案加 target、entitlements 寫進 project.yml、主 app 嵌入;最後實機驗證,並逐個 .appex 驗簽。
七個步驟
Seven steps
-
先確認帳號有 Family Controls 權限
First, check your account has Family Controls
Family Controls 是要向 Apple 申請的受限權限。RestBud 在 7/30 通過(帳號層級),之後新建的 App ID,Family Controls 的兩個選項直接就勾得起來。不過 Apple 的文件說得更嚴格:extension 要比照主 app 設定,上架時也要為 extension 提出同樣的申請。如果你的帳號勾不起來,先處理這件事(App ID 頁面上有個 Capability Requests 分頁,我這次用不到)。
來源:Apple · Configuring Family Controls -
手動建立新的 App ID
Create the new App ID by hand
Certificates, Identifiers & Profiles → Identifiers → + → App IDs → App。Description 填
rexcode restbud report;Bundle ID 選 Explicit(不是 Wildcard),填app.rexcode.restbud.report。Description 不能有 @ & * " 這類特殊字元(欄位底下會提醒),它只是給人看的標籤,真正的識別是 Bundle ID。為什麼手動建?我的經驗是,Xcode 自動幫你建的 App ID(名字開頭是「XC app …」)只會開 App Groups,不會開 Family Controls,最後還是得回後台補勾。
來源(建立步驟):Apple Developer Help · Register an App ID建好之後點進去就是這個畫面:Description、Bundle ID(explicit)和 Capabilities 分頁;App Groups 已勾,旁邊寫著 Enabled App Groups (1)。點圖可看原尺寸。
-
Family Controls:Development 和 Distribution 都要勾
Family Controls: tick both Development and Distribution
在這個 App ID 的頁面找到 Family Controls (Development) 和 Family Controls (Distribution),開發用和上架用各一個,兩個都勾。
另外還有第三個 App and Website Usage:那是 iOS 26.4 開給歐盟的資料讀取通道(Apple 文件寫明只有歐盟的裝置能用,見上面〈為什麼 RestBud 自己「看不到」這些數字〉)。台灣用不到,我在 entitlements 裡不宣告它。
來源:Apple · Configuring Family Controls · Apple · approvedWithDataAccess -
勾 App Groups,並指定到同一個 group
Tick App Groups and assign the same group
App Group 本身要先註冊好(Identifiers → + → App Groups,識別字必須以
group.開頭),RestBud 的早就有了。接著在這個 App ID 勾選 App Groups,再按旁邊的按鈕(Apple 的說明寫 Configure,我的畫面上設定完之後是 Edit),會跳出「App Group Assignment」:勾group.app.rexcode.restbud→ Continue → Assign → Done。四個 target 都指到同一個 group——主 app、monitor、shield 早就指好了,這次補上 report。App Group Assignment:把共用的 group 指給這個 App ID。左邊 group app rexcode restbud 是建立 group 時填的描述(給人看的標籤),右邊 group.app.rexcode.restbud 才是程式裡用的識別。
來源:Apple Developer Help · Enable app capabilities · Register an App Group · Apple · Configuring app groups -
Save → Confirm,然後 profile 會失效
Save → Confirm — and the profiles go stale
按 Save,跳出警告對話框就按 Confirm。Apple 的提醒是:包含這個 App ID 的 provisioning profile 會因為修改而失效,必須重新產生。用自動簽章(或 cloud signing)的話,通常會在下一次 build 時重新產生;手動管理 profile 的人要自己去重生。
來源:Apple Developer Help · Enable app capabilities -
專案端:加第四個 target
In the project: add the fourth target
我用 xcodegen,在
project.yml新增一個 target,並讓主 app 嵌入它:RestBud: # main app sources: - RestBud - Shared - path: RestBudReport/ReportContext.swift # scene id, shared by both dependencies: - target: RestBudReport # embed the report extension RestBudReport: type: app-extension platform: iOS sources: [RestBudReport] info: path: RestBudReport/Info.plist properties: NSExtension: NSExtensionPointIdentifier: com.apple.deviceactivityui.report-extension settings: base: PRODUCT_BUNDLE_IDENTIFIER: app.rexcode.restbud.report entitlements: path: RestBudReport/RestBudReport.entitlements properties: # declare entitlements HERE com.apple.developer.family-controls: true com.apple.security.application-groups: - group.app.rexcode.restbud- entitlements 一定寫在
properties:XcodeGen 的文件寫明,spec 裡一旦定義了 entitlements,它就會「產生並寫入」.entitlements 檔,所有項目都必須寫在properties裡。只留 path、自己手改檔案的話,下一次xcodegen generate就會被蓋掉——我另一個 App 就被蓋成空的<dict/>。 - 場景識別字串(context)兩邊要一致:主 app 用
DeviceActivityReport(context, filter: …)指名要哪一個畫面,extension 也要註冊同名的場景。我把定義放在同一個檔,讓兩個 target 都編進去。(我最後註冊了中、英各一個,原因在〈踩過的雷〉。) - 主 app 要自己給高度:報表是系統嵌進來的 remote view,實測不會自己撐高,要明確寫
.frame(height:)。 - filter 一定要帶
applications::Apple 的DeviceActivityFilter文件只說它是「要納入報表的 App(可省略)」,沒寫省略時的行為。依我的理解,沒帶就是不限 App,會把這支手機所有 App 都算進去——那不是家長想看的範圍。
- entitlements 一定寫在
-
實機驗證,以及打包前的最後一關
Verify on a real device — and the last check before shipping
模擬器沒有 Family Controls 授權,報表永遠是空白;加上主 app 讀不到裡面的數字,連 log 都沒有,所以只能在實機用眼睛驗。我訂的驗收標準:區塊出現;納管的 App 都在;沒納管的不出現;合計等於各列相加;分鐘數跟「設定 → 螢幕使用時間」同一個量級(差幾分鐘可以);語言跟 App 內設定一致;列不被截掉。其中「合計」和「語言」這兩條,是實機第一眼之後才補上的。
打包前把 .ipa 解開,對每一個
.appex跑codesign -d --entitlements -,確認四個 target 的 entitlements 都真的在。注意:命令列自動簽章的 build 會挑 Apple Development 憑證(get-task-allow=true),只能證明 entitlement 這條鏈通了,不是能上傳的成品。
踩過的雷
Pitfalls
🔴 extension 的 App ID 不會繼承主 app 的 capability。8/29 到 10/3,整整五週:主 app 的 App ID 開了 Time Sensitive Notifications,monitor 的卻沒開,monitor 的 profile 產不出來,命令列 build 一路紅,三份送審包全卡在這裡。Xcode 的錯誤訊息建議你把那個 entitlement 從檔案裡移掉——這個建議是錯的,entitlements 檔沒有問題,該做的是回後台勾 capability。
診斷法:把 ~/Library/Developer/Xcode/UserData/Provisioning Profiles 裡的 .mobileprovision 用 security cms -D -i 解開看 Entitlements(Apple 的 TN3125 就是教這個指令,並說明 profile 裡的 entitlements 是一份「允許清單」,App 宣告的每一項都必須在清單裡);如果這份 profile 的 CreationDate 是今天、卻還是缺那個 entitlement,就是後台沒開,不是本機快取。這次所以把後台放在第一步。
🟠 實機第一眼:「今天合計 1 小時 47 分」,列表卻是空的。系統交給報表的每一段用量(ActivitySegment)有一個 totalActivityDuration,Apple 對它的定義是「這段期間裝置螢幕亮著的總時間」——本來就是裝置層級的數字,我實測它也不受 filter 的 applications 限制。我第一版直接拿它當合計,所以孩子用了清單以外的 App 時,就會出現總數很大、列表卻是空的。修法:合計一律由納管 App 各自的時數自己加總;列表空就是 0。
🟠 實機第一眼:系統是中文,報表卻畫英文。報表 extension 的沙盒讀不到使用者的語言(Locale.preferredLanguages 在裡面回的是英文),filter 也帶不了自訂資料。主 app 唯一能傳進去的是 context 字串——所以我註冊了兩個場景(todayUsage.zh/todayUsage.en),由主 app 依自己的語言設定選一個嵌入。副作用是對的:這塊嵌在家長頁裡,本來就該跟 App 內的語言設定一致。(Monitor 和 Shield 兩個 extension 讀得到系統語言,只有報表有這個限制。這點 Apple 的文件沒有提到,是實測的結果。)
數字是起點,不是判決。先連續看幾天,找出哪個時段、哪個 App 最容易讓「一下」變成「很久」,再用課表把那一段換成全家都同意的規則。WHO 那份指引的全名其實是「身體活動、久坐行為與睡眠」——螢幕只是其中一格,睡覺和跑跳才是主角。RestBud 免費、零廣告、不收集任何資料。
延伸閱讀:「再五分鐘」的拉鋸戰,我把它做成一張課表 · RestBud 介紹頁 · 所有隨筆
本文是家長衛教與開發經驗的整理,不是醫療建議。孩子的視力、睡眠或專注力若有疑慮,請諮詢兒科或眼科醫師。
資料來源
Sources
- WHO (2019): To grow up healthy, children need to sit less and play more · Guidelines on physical activity, sedentary behaviour and sleep for children under 5 years of age
- 國民健康署/衛福部:室外活動 猴塞雷(好視力)(2016) · 居家防疫狂用眼 Eye眼動起來 (2023)
- AAP (2026-01-20): AAP news release · AAP releases new media recommendations · Helping Kids Thrive in a Digital World: AAP Policy Explained
- Parry et al. (2021), Nature Human Behaviour: A systematic review and meta-analysis of discrepancies between logged and self-reported digital media use
- Apple Developer: DeviceActivityReport · DeviceActivityFilter · ActivitySegment.totalActivityDuration · approvedWithDataAccess · Configuring Family Controls · Configuring app groups
- Apple Developer Help: Register an App ID · Register an App Group · Enable app capabilities
- Apple Technote: TN3125: Inside Code Signing: Provisioning Profiles
- XcodeGen: ProjectSpec