On Demand Resources 已棄用:Background Assets 的代價
Apple 用 13 個字,終結了一套沿用十年的內容遞送機制:「On Demand Resources and the NSBundleResourceRequest API are deprecated. Use Background Assets instead.」1
這句話就是條目全文。它掛著 radar 170066290,歸在 Deprecations 底下,並在三份不同的發行說明中一字不差地重複出現。123 Apple 沒有公布移除版本,沒有針對此次棄用提供遷移指南,macOS 與 watchOS 的發行說明裡也找不到對應說明。
真正的工作量,藏在最後四個字裡。Background Assets 並非單一方案,而是分岔成三種組態,各自有不同的託管模式、不同的最低部署目標,遷移成本相差將近一個數量級。抉擇發生在您寫下第一行程式碼之前,而選錯正是代價最高的失誤。
TL;DR
- Apple 在 iOS 與 iPadOS 27、tvOS 27、visionOS 27 的發行說明中,將 On Demand Resources 與
NSBundleResourceRequest標記為棄用。123 ODR 仍可運作。Apple 未指定移除日期,已棄用的 API 依然隨系統出貨,也依然能解析標籤。 - 該 API 自身的可用性資料,在六個平台上標示棄用,比任何一份發行說明所提及的多出兩個:Mac Catalyst 與 watchOS。4 而 Background Assets 根本未公布任何 watchOS 可用性,換言之,watchOS 收到了一則沒有替代方案可循的棄用通知。56
- 「改用 Background Assets」實際上分成三條路:由 Apple 託管的受管理模式、自行託管的受管理模式,以及非受管理模式。兩種受管理路線都要求最低部署目標為 iOS 26.0。78 低於 26.0 就只剩非受管理這條路,而它要求您自行託管檔案、自行發明資訊清單格式,並自行解析。9
- 磁碟管理的責任歸屬完全反轉。ODR 讓系統自動清除未使用的標籤資源,
setPreservationPriority(_:forTags:)只是關於清除順序的提示。410 Background Assets 則會把每一個下載完成的資源包留在裝置上,直到您的程式碼呼叫remove(assetPackWithID:)為止。11 - Apple 為每筆 App 記錄託管的壓縮資源包上限為 200 GB、資源包數量上限為 200 個,且由您 App 支援的所有平台共用;這些資源包上傳至 App Store Connect,並與建置版本分開審查。1213
Apple 究竟棄用了什麼
這則說明中有三個關鍵細節,而說明本身一個都沒交代。
影響範圍比發行說明更廣。 收錄此條目的文件共三份:iOS 與 iPadOS 27、tvOS 27、visionOS 27,各自置於 On Demand Resources 標題下的 Deprecations 子標題中,並引用同一組 radar。123 macOS 27 與 watchOS 27 的說明則隻字未提。
API 的可用性註記說出了更完整的故事。NSBundleResourceRequest 標示為 iOS 9.0 引入、27.0 棄用,同樣的 27.0 棄用註記也出現在 iPadOS 9.0、Mac Catalyst 13.1、tvOS 9.0、visionOS 1.0 與 watchOS 2.0 上。4 中繼資料裡是六個平台,發行說明中點名的只有四個。Bundle 的兩個保留優先權方法也帶著同樣的六平台註記。10 只依據發行說明來稽核,等於完全漏掉 Mac Catalyst 與 watchOS 兩項。
Mac Catalyst 那一項只是名義上的。Apple 明確記載 NSBundleResourceRequest 會「忽略以 Mac Catalyst 建置的 Mac App 所發出的呼叫」,因此這次棄用退役的,是一個在該平台上從未起過作用的 API。4 watchOS 那一項就不只是名義問題了。Background Assets 列出的可用性為 iOS 16.0、iPadOS 16.0、Mac Catalyst 16.0、macOS 13.0、tvOS 18.4 與 visionOS 2.4,完全沒有 watchOS 這一列。5 Apple 也直言,由 Apple 託管的資源包「適用於透過 App Store 發行的 App,涵蓋 watchOS 以外的所有平台」。6 使用 ODR 的 watchOS App,只會收到一則棄用警告,卻沒有任何可遷移的去處。
在我報導過的三項 27 週期變更中,這一項的強制力最弱。 棄用就只是棄用而已。Apple 沒有公布移除版本、沒有設下送審關卡,也沒有任何執行期失敗。對照同一週期的場景生命週期強制規定,以新 SDK 建置的 App 會「無法啟動」;再對照啟動畫面規定,App Store 會直接退回建置版本。ODR 兩者皆非。既有標籤照常解析,既有呼叫照常回傳資源,已上架的二進位檔照常運作。真正到來的,只有一則編譯器警告,以及一個沒人讀得出刻度的倒數計時。
這個時間點讀起來像一項決策,而非例行清理。 Apple 一口氣在四個平台名稱上棄用了這個 API,而替代方案的受管理層級才剛在上一個版本推出。請把這次棄用視為一扇遷移窗口的開啟,只是 Apple 尚未公布這扇窗會開多久;它不是緊急事件。
寫程式之前就得決定的分岔
Apple 的框架總覽介紹了兩種託管模式,以及一個「為您處理下載、更新、壓縮等工作」的受管理預設值。若選擇 Apple 託管,則「您將資產上傳至 App Store Connect 並在該處維護,做法與 App 建置版本類似」。5 Xcode 的 Background Download extension 範本直接列出兩種類型:「Apple 託管、受管理」與「自行託管、非受管理」。911 第三種組合則存在於屬性清單索引鍵中:將 BAHasManagedAssetPacks 設為 YES 但不設定 BAUsesAppleHosting,即可選擇由您自行託管的受管理資源包,其文件也會將您導向 ManagedDownloaderExtension 協定,而非 StoreKit 的 StoreDownloaderExtension。7814
| Apple 託管、受管理 | 自行託管、受管理 | 自行託管、非受管理 | |
|---|---|---|---|
| 最低 iOS 版本 | 26.0715 | 26.0714 | 16.19 |
| 由誰託管檔案 | Apple,透過 App Store Connect6 | 您自己 | 您自己 |
| 資訊清單格式 | Apple 的 JSON 綱要11 | Apple 的 JSON 綱要11 | 由您自行發明並解析9 |
| Extension 協定 | StoreDownloaderExtension716 |
ManagedDownloaderExtension714 |
BADownloaderExtension9 |
| 下載、更新、壓縮 | 系統負責5 | 系統負責5 | 您負責9 |
| 屬性清單索引鍵 | 3 個11 | 未有完整文件7 | 4 個頂層鍵,其中一個再包 3 個9 |
對多數團隊而言,部署目標就是決定因素。所有受管理的進入點,從 AssetPackManager、ManagedDownloaderExtension 到那三個屬性清單索引鍵,全都至少要求 iOS 26.0。781415 支援 iOS 18 的 App 根本無法採用受管理層級,選項只剩下回溯支援到 iOS 16.1 的非受管理路線,或是在部署目標拉高之前繼續使用已棄用的 ODR。9
非受管理路線是另一份工作。Apple 設定的流程是:系統在您的 App 啟動前,先從 BAManifestURL 下載一份資訊清單,把檔案交給您的 extension,再收回一組下載請求。9 Apple 對權責的劃分毫不含糊:「為您自行託管的非受管理資產建立資訊清單檔案(格式由您自選),並由您的程式碼解析出 URL 與檔案大小交給系統,是您的責任。」9 託管、CDN、資訊清單綱要、解析器、網域允許清單,全都得由您供應。任何把「改用 Background Assets」讀成單純換 API 的人,都是拿受管理層級在讀說明、卻要付非受管理層級的帳單。
ODR 給過您、如今得自己重造的東西
ODR 有三項行為找不到可直接替換的對應物。
標籤變成資源包。 ODR 以在 Xcode 中指派的字串標籤來標示內容,再由 NSBundleResourceRequest(tags:) 認領其中一個或多個。4 Background Assets 則以資源包取代標籤:由 JSON 資訊清單描述的檔案目錄,經命令列工具壓縮成 .aar 封存檔。顆粒度的單位變大了,而指派工作也從 Xcode 的資產目錄,移到一份由您自行維護的檔案裡。
Apple 託管等於另一條發行軌道。 ODR 的內容是跟著建置版本一起走的。由 Apple 託管的資源包則透過 Transporter、altool、iTMSTransporter 或 App Store Connect API 獨立上傳,並與 App 分開送交 App Review。1113 這種解耦正是它的價值所在:不用發布新建置版本,就能推出新內容。代價則是多出一條送審管線、一個審查佇列,以及另一組需要盯著的狀態。
自動清除變成您的工作,而這正是最劇烈的一次反轉。 ODR 把下載的內容視為由系統掌管的快取。Apple 記載,只要「至少還有一個 NSBundleResourceRequest 物件正在管理該標籤,系統就不會嘗試從裝置儲存空間清除以該標籤標示的資源」,這是一個關於「何時清除」而非「是否清除」的承諾。4 setPreservationPriority(_:forTags:) 存在的用意,正是提供「關於 bundle 中各標籤資源集合清除相對順序的提示」。10 您結束認領,系統便依自己的節奏回收空間,儲存空間不足的處理是 Apple 的問題。
Background Assets 把所有權整個顛倒過來。系統會自動保持資源包更新,checkForUpdates() 也會移除伺服器端已淘汰的資源包。15 但這兩種機制,都不會驅逐一個您單純用完了的資源包。Apple 的指示寫得很白:「只要您的 App 仍在安裝狀態,系統就不會自動移除您的資源包。因此,當您用完某個資源包時,請呼叫 remove(assetPackWithID:) 方法。」11
原本有作用域、以參照計數運作的模式,塌縮成一個必須由您主動決定去呼叫的明確刪除動作:
// ODR: claim a tag, use the file, release the claim.
// The system reclaims the space afterward on its own schedule.
let request = NSBundleResourceRequest(tags: ["Tutorial"])
try await request.beginAccessingResources()
let url = Bundle.main.url(forResource: "Introduction", withExtension: "m4v")
request.endAccessingResources()
import System // url(for:) and contents(at:) take a FilePath
// Background Assets: ensure the pack, read the file, delete the pack.
// Nothing reclaims the space if you skip the last line.
let manager = AssetPackManager.shared
guard let pack = try await manager.manifest.assetPack(withID: "Tutorial") else { return }
try await manager.ensureLocalAvailability(of: pack, requireLatestVersion: false)
let url = try manager.url(for: "Videos/Introduction.m4v")
try await manager.remove(assetPackWithID: "Tutorial")
任何內建了「ODR 會自動驅逐」這項假設的 App,都需要為它重寫一份儲存空間政策。失效模式很安靜:不會當機、不會警告,裝置儲存空間就一路往上爬,直到使用者在儲存空間列表裡注意到您的 App。
遷移面,逐項拆解
以 Apple 託管的受管理路線為例,Apple 自家的步驟可整理成以下檢查清單。
把檔案分組成資源包,並為每個資源包挑選下載政策。政策共有三種。essential 在安裝期間下載,並計入使用者在 App Store、TestFlight 與主畫面上看到的進度。prefetch 於安裝期間啟動,並在安裝完成後於背景繼續。onDemand 則只在您的程式碼提出要求時才下載。11 對 essential 與 prefetch 而言,巢狀的 installationEventTypes 陣列可接受 firstInstallation、subsequentUpdate 或兩者,因此教學用的資源包可以只在首次安裝時下載,往後的每次更新都略過。11
為每個資源包撰寫一份資訊清單。Xcode 會產生一份含註解的範本:
xcrun ba-package template -o Manifest.json
{
"assetPackID": "Tutorial",
"downloadPolicy": {
"essential": {
"installationEventTypes": ["firstInstallation"]
}
},
"fileSelectors": [
{ "file": "Videos/Introduction.m4v" },
{ "directory": "Textures/Tutorial" }
],
"platforms": ["<identifiers from the generated template comments>"]
}
檔案路徑是相對於您執行封裝指令的目錄來解析的,這一點在稍後依路徑讀回檔案時會再次派上用場。11 接著封存每個資源包:
xcrun ba-package Manifest.json -o Tutorial.aar
在 Application Extension 底下新增一個 Background Download extension target,類型選擇「Apple 託管、受管理」。為 App 與 extension 雙方都加上 App Groups 能力,並將兩者放進同一個群組。然後為 App target 加入三個屬性清單索引鍵:BAAppGroupID、設為 YES 的 BAHasManagedAssetPacks,以及設為 YES 的 BAUsesAppleHosting。Apple 指示,Apple 託管的專案應省略其他所有 Background Assets 索引鍵。11 有一項限制很容易踩到:採用 AssetPackManager 卻未一併採用對應的 extension 協定,用 Apple 的話說,是「程式設計錯誤」。15
讀回檔案是透過一個合併後的命名空間進行。Apple 會「自動將您所有的資源包合併到一個共用命名空間中,效果等同於把您的資產根資料夾原封不動貼到使用者裝置上」,因此程式碼只需依路徑定址檔案,無須追蹤該檔案屬於哪個資源包。11 讀取預設回傳記憶體映射的 Data,另有一種供程序化載入使用的檔案描述符變體,但必須由您自行關閉。11
本機測試的環境設定成本,值得單獨編列。Background Assets 的每一次下載都走 HTTPS,所以模擬伺服器需要憑證。Apple 記載的流程包括:透過「鑰匙圈存取」建立自我簽署的根 CA,用 Apple Configurator 製作一份帶有該 CA 的描述檔,在每一台測試裝置上安裝並信任該描述檔,簽發一張名稱必須與伺服器 IP 位址或主機名稱完全相符的 SSL 末端憑證,啟動伺服器,最後在每台裝置的「開發者」設定中設定 URL 覆寫。17
xcrun ba-serve --host localhost Tutorial.aar HighQualityTextures.aar
請把這整段流程當成一項獨立任務來編列。On Demand Resources 從頭到尾都不需要您自備任何伺服器:Apple 將它描述為管理「託管於 App Store 的內容」的機制,裝置上缺少的資源「會向 App Store 請求」。4 遷移意味著在您能跑起第一次下載之前,得先架好託管環境,或是一個受信任的模擬版本。把兩套工作流程並排讀下來,我預期吃掉遷移第一天的會是憑證鏈,而不是 API 本身的採用。
該用來規劃的數字
Apple 為託管資源包公布了兩道硬上限:總量 200 GB,以及每筆 App 記錄 200 個資源包。兩者皆「由您 App 所提供的所有平台共用」。12 Apple 以符合 TestFlight 或 App Store 發行資格的各版本中的最大尺寸來計算總量,並排除 Awaiting Upload、Processing、Failed 以及已完全被取代的版本,達到上限 80% 時會寄送電子郵件通知。封存某個資源包可回收空間,做法是移除它的所有版本,包括已在 App Store 上線的版本。12
非受管理路線則把這些上限,換成四個由您自行設定的頂層屬性清單索引鍵,其中一個還是內含另外三項的字典;而壓縮與未壓縮之間的區別是個名副其實的陷阱。BADownloadAllowance 與 BAEssentialDownloadAllowance 用來限制下載大小,填入的是壓縮後的數值。BAMaxInstallSize 與 BAEssentialMaxInstallSize 用來限制安裝後大小,填入的是未壓縮的數值。9 Apple 在安裝大小這組索引鍵上附了一則警告,本質上是產品層面的警告:「App Store 會用這個索引鍵在產品頁面上顯示您 App 的大小,請提供準確的數值……請勿誇大您所需的磁碟空間。」18 BADownloadDomainAllowList 則補齊了這組設定,它接受 DNS 格式的網域,開頭可加上星號作為萬用字元。9
還有一個數字該納入規劃,而它來自可用性中繼資料,不是敘述文字。AssetPackManager 隨 iOS 26.0 推出,如今已有四個成員標示棄用:ensureLocalAvailability(of:) 與 status(ofAssetPackWithID:) 於 26.4 棄用,接著 assetPack(withID:) 與 allAssetPacks 於 27.0 棄用。19 查詢、狀態與下載呼叫,各自在兩個小改版之間搬動過一次。Apple 目前指向的路徑,也就是透過管理器的 manifest 屬性,在 27.0 的 SDK 中帶有 beta 註記,批次版本的 ensureLocalAvailability(of:requireLatestVersions:) 亦然。19 而 Apple 自家關於 Apple 託管的逐步教學,至今仍在示範其中兩個已棄用的呼叫。11 因此,實務上的門檻其實高於該層級名義上的 26.0。想寫出前文那段下載程式碼又不吃到棄用警告,就得以 27.0 為目標,並接受過程中會用到標示 beta 的符號。您被要求採用的替代方案,比它所取代的 API 更年輕,也變動得更快。
這次棄用實際會波及誰
受影響的族群很窄,窄到我在自己的程式碼裡一個都找不到。我在七個已上架專案中搜尋了 NSBundleResourceRequest、beginAccessingResources、setPreservationPriority、任何 ON_DEMAND_RESOURCES 建置設定、knownAssetTags,以及資產目錄的標籤設定。七個專案、每一種模式,命中數皆為零。針對我專案目錄下所有 Swift、Objective-C、屬性清單與 pbxproj 檔案做的全庫掃描,沒有找到任何 ODR 符號,也沒有找到任何 Background Assets 符號。20
這個零結果背後的原因值得點名,因為它具有普遍性。ODR 存在的理由,是為了那些內容量遠大於程式碼量的 App。我最大的資產目錄屬於 Return,66.6 MB,其餘每個 App 都在 8 MB 以下,Water 與 Yawara 甚至不到 100 KB。20 在這種量級下,把內容拆成資源包,只會增加網路失效模式、一份儲存空間政策與第二條審查管線,省下的卻是一份沒人抱怨過的下載量。真正需要 Background Assets 的,是帶有關卡內容的遊戲、隨附大型機器學習模型的 App,以及任何具備逐語言影片的產品——這恰好正是 Apple 在 iOS 27 推出在地化資源包支援所鎖定的族群。21
部署目標讓輪廓更加清晰,而它也是任何程式碼庫裡該最先檢查的數字。我六個 iOS App 中有五個,部署目標已經落在 iOS 26.0 或更高,因此受管理層級今天就能為它們所用。Ace Citizenship 的部分 target 仍宣告 17.0 與 17.5,這會排除受管理層級,只留下非受管理路線或已棄用的 ODR。20 動手設計任何東西之前,先跑這項檢查:決定您實際上被提供哪一種遷移方案的,是最低部署目標,而不是資產的體積。
FAQ
On Demand Resources 在 iOS 27 會停止運作嗎?
不會。Apple 將 ODR 與 NSBundleResourceRequest 標記為棄用,但未公布移除版本、未設下送審關卡,也沒有任何執行期失敗。1 已棄用的 API 仍能繼續運作,既有標籤照常解析。您得到的只是一則編譯器警告。與同一週期其他破壞性變更的對比很有啟發性:場景生命週期強制規定會讓 App「無法啟動」,啟動畫面規定則會讓 App Store 退回建置版本。ODR 這次棄用啟動的是一個倒數計時,而不是關上一道門。
這次棄用涵蓋哪些平台?
發行說明在三份文件中點名了四個平台:iOS 與 iPadOS 27、tvOS 27、visionOS 27,全都引用 radar 170066290。123 而 API 的可用性中繼資料範圍更廣,把 NSBundleResourceRequest 與 Bundle 的保留優先權方法,在六個平台上標示為 27.0 棄用,多出 Mac Catalyst 與 watchOS。410 Mac Catalyst 只有理論意義,因為 Apple 記載該類別會忽略來自 Catalyst App 的呼叫。4 watchOS 就不只是理論了:Background Assets 未公布任何 watchOS 可用性,且 Apple 託管的資源包適用範圍是「watchOS 以外的所有平台」,因此 watchOS App 手上握著一個已棄用的 API,卻沒有任何有文件可循的後繼者。56
如果我的 App 支援 iOS 18,還能遷移嗎?
無法遷移到受管理層級。AssetPackManager、ManagedDownloaderExtension、BAHasManagedAssetPacks 與 BAUsesAppleHosting 全都要求 iOS 26.0。781415 在這道門檻以下還剩兩個選項。非受管理路線從 iOS 16.1 起可用,但它要求您自行託管資產、定義自己的資訊清單格式、在 extension 中解析它,並在屬性清單裡宣告下載額度與網域允許清單。9 否則,就繼續使用已棄用的 ODR,直到部署目標推進到 26.0——鑑於 Apple 至今未給出移除日期,目前這麼做是被允許的。
如果直接把 ODR 程式碼原封不動移植過去,什麼會悄悄壞掉?
儲存空間。ODR 讓系統清除未使用的標籤內容,而 setPreservationPriority(_:forTags:) 也只是對順序的提示。410 Background Assets 則在您的 App 保持安裝狀態期間,絕不會移除任何一個您已用完的資源包,因此在您呼叫 remove(assetPackWithID:) 之前,那些空間都算您的。11 若程式碼只是照搬舊有的 beginAccessingResources 與 endAccessingResources 模式,卻沒有補上明確的刪除動作,磁碟就會無止境地漏下去,既不會當機,也不會有任何警告能在測試階段攔下它。請在寫下載程式碼之前,先寫好清除政策。
重點整理
給 iOS 開發者:
- 在做任何事之前,先確認最低部署目標。低於 iOS 26.0,受管理層級對您而言並不存在,「改用 Background Assets」意味著要在非受管理路線上自建託管、資訊清單格式與解析器。79
- 把清除政策當作遷移工作的一部分寫出來。remove(assetPackWithID:) 沒有自動化的對應物,而 ODR 那套「放掉認領、交給系統」的習慣,只會讓儲存空間無聲地一路膨脹。11
給發行大型內容的團隊: - 本機測試環境的建置成本,請與程式碼工作分開編列。Apple 記載的流程要經過自我簽署根 CA、一份在每台裝置上安裝並信任的 Apple Configurator 描述檔、一張與伺服器主機名稱相符的 SSL 末端憑證,以及逐台裝置的 URL 覆寫。17 - 以 200 GB 與每筆 App 記錄 200 個資源包來規劃,額度由您 App 出貨的所有平台共用,並留意 Apple 在達到 80% 時寄出的電子郵件。12 為回收空間而封存,會一併移除已在 App Store 上線的版本。12
給發行管理者: - Apple 託管的資源包意味著第二條送審管線:透過 Transporter 或 App Store Connect API 上傳、與建置版本各自獨立版本控管,並單獨送交 App Review。1113 請據此配置審查週期的人力。 - 這個週期沒有任何東西在逼您遷移。請把 ODR 排在場景生命週期強制規定與啟動畫面規定之後——那兩項帶有真正的強制力——等 Apple 公布移除版本時再回頭處理。
27 週期持續依「牙齒鋒不鋒利」在為自己的破壞性變更分級:場景生命週期讓 App 開不起來,啟動畫面讓建置版本上不了架,而 ODR 只是啟動了一個倒數計時。分得清哪個是哪個,就是把這個週期過好的方法。想看同一套模式在更小的表面上如何上演,請參閱 ImageCreator 自 Image Playground 移除。完整系列的匯整頁面是 Apple 生態系系列。
參考資料
-
Apple, iOS & iPadOS 27 Release Notes, On Demand Resources section, Deprecations (radar 170066290):「On Demand Resources and the
NSBundleResourceRequestAPI are deprecated. Use Background Assets instead.」已於 2026 年 7 月 25 日對照 Apple 文件 JSON 查證。該條目即為全文;發行說明中沒有關於 On Demand Resources 的移除版本、送審要求或執行期失敗的任何文字。 ↩↩↩↩↩↩ -
Apple, tvOS 27 Release Notes, On Demand Resources section, Deprecations (radar 170066290)。措辭與 iOS 及 iPadOS 的條目完全相同。 ↩↩↩↩
-
Apple, visionOS 27 Release Notes, On Demand Resources section, Deprecations (radar 170066290)。措辭完全相同。macOS 27 與 watchOS 27 的發行說明沒有對應條目,已於 2026 年 7 月 25 日搜尋其文件 JSON 查證。 ↩↩↩↩
-
Apple, NSBundleResourceRequest, Foundation。可用性:iOS 9.0、iPadOS 9.0、Mac Catalyst 13.1、tvOS 9.0、visionOS 1.0 與 watchOS 2.0,各自於 27.0 棄用。此為標籤模型(「您在開發期間透過建立稱為標籤的字串識別碼來標示隨選資源」)、清除行為(「只要至少還有一個
NSBundleResourceRequest物件正在管理該標籤,系統就不會嘗試從裝置儲存空間清除以該標籤標示的資源」)、Mac Catalyst 註記(「此類別會忽略以 Mac Catalyst 建置的 Mac App 所發出的呼叫」)以及單次使用限制的出處。成員 APIinit(tags:)、beginAccessingResources(completionHandler:)與endAccessingResources()帶有相同的六平台 27.0 棄用註記。 ↩↩↩↩↩↩↩↩↩↩ -
Apple, Background Assets, framework overview。可用性:iOS 16.0、iPadOS 16.0、Mac Catalyst 16.0、macOS 13.0、tvOS 18.4 與 visionOS 2.4,沒有 watchOS 這一列。此為「The default implementation of Managed Background Assets handles downloads, updates, compression, and more for you」與「If you choose Apple-Hosted Background Assets, you upload your assets to App Store Connect and maintain them there, similar to app builds」的出處。 ↩↩↩↩↩↩
-
Apple, Creating managed asset packs, Background Assets。此為「Apple-Hosted Background Assets can host up to 200GB of compressed assets and is available for apps distributed through the App Store on all platforms except watchOS」的出處。 ↩↩↩↩
-
Apple, BAHasManagedAssetPacks, Information Property List reference。布林值,iOS 26.0、iPadOS 26.0、macOS 26.0、tvOS 26.0 與 visionOS 26.0。此為 extension 協定路由的出處:「use the StoreKit
StoreDownloaderExtensionprotocol if you set theBAUsesAppleHostingkey toYES; otherwise, use the Background AssetsManagedDownloaderExtensionprotocol.」這段路由說明記錄了受管理、自行託管的組合,而各篇逐步教學文章並未完整涵蓋這個組合。 ↩↩↩↩↩↩↩↩↩↩ -
Apple, BAUsesAppleHosting 與 BAAppGroupID, Information Property List reference。兩者皆標示 iOS 26.0、iPadOS 26.0、macOS 26.0、tvOS 26.0 與 visionOS 26.0。請注意,
BAAppGroupID、BAHasManagedAssetPacks與BAUsesAppleHosting除了其他平台的 26.0 之外,都各帶有一列異常的 Mac Catalyst 16.0;受管理層級的 iOS 26.0 門檻,是建立在AssetPackManager、ManagedDownloaderExtension與BAHasManagedAssetPacks之上,而非建立在非受管理路線同樣需要的BAAppGroupID之上。 ↩↩↩↩ -
Apple, Configuring an unmanaged Background Assets project, Background Assets。此為 Self-Hosted, Unmanaged extension 類型、雙方 target 皆須具備 App Groups、安裝與更新的下載流程,以及權責聲明的出處:「It’s your responsibility to create manifest files for your self-hosted, unmanaged assets (using your format of choice) that your code parses to get the URLs and file sizes to the system.」同時也是
BAManifestURL、BAInitialDownloadRestrictions、BADownloadAllowance與BAEssentialDownloadAllowance(壓縮後大小)、BAMaxInstallSize與BAEssentialMaxInstallSize(未壓縮大小),以及BADownloadDomainAllowList(DNS 格式網域,開頭可加星號作為萬用字元)的出處。BADownloaderExtension自 iOS 16.1、iPadOS 16.1、Mac Catalyst 16.1、macOS 13.0、tvOS 18.4 與 visionOS 2.4 起可用;BAManifestURL自 iOS 16.1 起可用。 ↩↩↩↩↩↩↩↩↩↩↩↩↩↩ -
Apple, setPreservationPriority(_:forTags:) 與 preservationPriority(forTag:), Foundation。兩者皆於 iOS 9.0 引入,並在 iOS、iPadOS、Mac Catalyst、tvOS、visionOS 與 watchOS 上於 27.0 棄用。此為「A hint to the system of the relative order for purging tagged sets of resources in the bundle」的出處。 ↩↩↩↩↩
-
Apple, Downloading Apple-hosted asset packs, Background Assets,並搭配 Creating managed asset packs。此為以下內容的出處:Background Download extension 範本及其 Apple-Hosted, Managed 類型、共用 app group 的要求、三索引鍵的屬性清單設定連同「omit all other Background Assets information property list keys」的指示、
xcrun ba-package template與xcrun ba-package指令、資訊清單索引鍵(assetPackID、downloadPolicy、含firstInstallation與subsequentUpdate的installationEventTypes、含file與directory的fileSelectors,以及platforms)、三種下載政策(essential、prefetch與onDemand)及其安裝行為、路徑相對於封裝目錄的規則、合併命名空間(「The system automatically merges all of your asset packs into a shared namespace, effectively reconstructing your asset root folder as if it were pasted on a person’s device」)、記憶體映射的Data讀取與檔案描述符變體、上傳管道(Transporter、altool、iTMSTransporter 與 App Store Connect API),以及儲存空間指示:「the system won’t automatically remove your asset packs while your app is installed. Therefore, when you are done with an asset pack, call theremove(assetPackWithID:)method.」本文的下載範例同時呼叫了assetPack(withID:)(Apple 的可用性資料標示於 27.0 棄用)與ensureLocalAvailability(of:)(於 26.4 棄用,參見註 19)。 ↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩ -
Apple, Apple-hosted asset pack size limits, App Store Connect Help。資源包總量 200 GB;資源包數量 200 個。此為「The total sum of size usage for all asset packs uploaded to an app record in App Store Connect」、計算方式(取符合 TestFlight 或 App Store 發行資格之各版本中的最大尺寸,排除 Awaiting Upload、Processing、Failed 及已完全被取代的版本)、80% 電子郵件通知、「These limits are shared across all platforms offered for your app」,以及封存行為「removes all versions of an asset pack from App Store Connect, including those being tested in TestFlight and live on the App Store」的出處。 ↩↩↩↩↩
-
Apple, Overview of Apple-hosted asset packs, App Store Connect Help。此為四步驟工作流程(封裝、上傳、透過 TestFlight 測試、送交 App Review)、資源包獨立於 App 建置版本之外,以及受管理 Apple 託管資產所支援的平台清單(iOS 26+、iPadOS 26+、macOS 26+、tvOS 26+ 與 visionOS 26+)的出處。 ↩↩↩
-
Apple, ManagedDownloaderExtension, Background Assets。協定,在列出的六個平台上皆為 iOS 26.0 起可用。它為所有繼承自
BADownloaderExtension的需求提供預設實作,並警告除了可選的backgroundDownload(_:didReceive:)之外,不要自行實作這些繼承而來的需求。 ↩↩↩↩↩ -
Apple, AssetPackManager, Background Assets。Actor,iOS 26.0、iPadOS 26.0、Mac Catalyst 26.0、macOS 26.0、tvOS 26.0 與 visionOS 26.0。此為選用加入註記(「The first time that your code refers to the shared manager, Background Assets considers that your app is opting into automatic system management of your asset packs」)以及配對要求的出處:採用該管理器卻未搭配對應的受管理 extension 協定,是「a programmer error」。同時也是
checkForUpdates()(「Gets the latest asset-pack information from the server, updates outdated asset packs, and removes obsolete asset packs」)以及remove(assetPackWithID:)、url(for:)(nonisolated,接受FilePath並回傳URL)與statusUpdates(forAssetPackWithID:)的出處,這幾者均未標示棄用。AssetPack與ManagedBackgroundAssetsError帶有相同的 iOS 26.0 可用性。至於該管理器已棄用的成員,參見註 19。 ↩↩↩↩↩ -
Apple, StoreDownloaderExtension, StoreKit。此協定精煉自
ManagedDownloaderExtension,可用於 iOS 26.0、iPadOS 26.0、macOS 26.0、tvOS 26.0 與 visionOS 26.0。 ↩ -
Apple, Testing asset packs locally, Background Assets。此為 HTTPS 要求、「鑰匙圈存取」根 CA 流程、Apple Configurator 描述檔的製作與逐台裝置的安裝與信任步驟、名稱必須是與伺服器相符之「a valid IP address, hostname, or domain name」的 SSL 末端憑證、
xcrun ba-serve指令,以及「開發者」設定中的 URL 覆寫(iOS、iPadOS、tvOS 與 visionOS 上為「設定」>「開發者」>「Development Overrides」;macOS 上為xcrun ba-serve url-override)的出處。 ↩↩ -
Apple, BAEssentialMaxInstallSize 與 BAMaxInstallSize, Information Property List reference。
BAEssentialMaxInstallSize自 iOS 18.0 起,BAMaxInstallSize自 iOS 16.0 起。兩者皆載明:「The App Store uses this key to show the size of your app on the product page, so provide an accurate value. If you compress the assets, use the uncompressed size of the files for this value. Don’t overstate the disk space you require.」兩者皆標示為使用 Background Assets 的必要項目。 ↩ -
AssetPackManager各成員的 Apple 可用性中繼資料,於 2026 年 7 月 25 日自 Apple 文件 JSON 讀取。已棄用成員(全部於 iOS 26.0 引入):ensureLocalAvailability(of:) 於 26.4 棄用;status(ofAssetPackWithID:) 於 26.4 棄用,改用status(relativeTo:);assetPack(withID:) 於 27.0 棄用,並附註「CallassetPack(withID:)on the manager’smanifestproperty’s value」;allAssetPacks 於 27.0 棄用,改用資訊清單的assetPacks屬性。於 iOS 27.0 引入、且在目前 SDK 中標示為 beta 的替代符號:manifest、AssetPackManifest.assetPack(withID:)(同步,回傳選擇性的AssetPack)與 ensureLocalAvailability(of:requireLatestVersions:)。ensureLocalAvailability(of:requireLatestVersion:) 於 26.4 推出,未標示棄用。至於「Apple 的 Apple 託管逐步教學至今仍在示範兩個已棄用的呼叫」(assetPack(withID:)與ensureLocalAvailability(of:))這項觀察,屬作者所見,依據為同一日期將文章內文與符號可用性相互比對的結果。 ↩↩ -
作者於 2026 年 7 月 25 日對七個已上架專案所做的普查:Reps、Return、Banana List、Ace Citizenship、Water、ResumeGeni 與 Yawara。搜尋了每一個 Swift、Objective-C、標頭、屬性清單與
project.pbxproj檔案(排除build、DerivedData、.build、Pods與.git),目標為NSBundleResourceRequest、beginAccessingResources、setPreservationPriority、On Demand Resources、任何ON_DEMAND_RESOURCES建置設定、knownAssetTags以及ASSETCATALOG_COMPILER_*TAG設定。每個專案在每一種模式上的命中數皆為零,Background Assets 符號的命中數也為零。資產目錄總量以du對所有.xcassets目錄量測,排除建置輸出、fastlane 螢幕截圖與報告目錄:Return 66.62 MB、Ace Citizenship 7.81 MB、Banana List 2.04 MB、Reps 1.66 MB、Water 0.04 MB、Yawara 0.01 MB。自各個project.pbxproj讀取的IPHONEOS_DEPLOYMENT_TARGET值:Reps 26.0 與 26.2、Return 26.1、Banana List 26.0、Water 26.0、Yawara 26.5,而 Ace Citizenship 在其各個 target 上為 17.0、17.5 與 26.1。 ↩↩↩ -
Apple, Reducing download and storage demands with localized asset packs, Background Assets。此為 macOS 27、iOS 27、tvOS 27 與 visionOS 27 中為資源包新增之
language指定、BCP-47 識別碼規則(僅限語言、地區與文字系統子標籤,不含變體或擴充)以及 Xcode 27 範本language索引鍵的出處。 ↩