Dunfey · Hotel WWDC as data, est. 1983
Front desk everything
Years
Topics

2025 App ServicesApp Store, Distribution & MarketingGraphics & GamesSystem Services

WWDC25 · 25 min · App Services / App Store, Distribution & Marketing / Graphics & Games / System Services

Discover Apple-Hosted Background Assets

Building on Background Assets, this session will introduce the new capability to download asset packs of content for games and other applications. Learn how Apple can host these asset packs for you or how to manage self-hosting options. We’ll delve into the native API integration and the corresponding App Store implementations, providing you with the tools to enhance your app’s content delivery and user experience.

Watch at developer.apple.com ↗

Transcript all transcripts

Chapters

  • 0:00 — Introduction
  • 1:01 — New in Background Assets
  • 7:32 — Sample app development
  • 17:24 — Beta testing and distribution

Code shown on screen · 9 snippets

Fill out the manifest json · at 8:26 ↗
{
	"assetPackID": "[Asset-Pack ID]",
	"downloadPolicy": {
		"essential": { // Possible keys: “essential”, “prefetch”, or “onDemand”
			// Essential and prefetch download policies require a list of installation event types. For an on-demand download policy, the value for the “onDemand” key must be an empty object.
			"installationEventTypes": [
				// Remove undesired elements from this array.
				"firstInstallation",
				"subsequentUpdate"
			]
		}
	},
	"fileSelectors": [
		// You can add as many file and/or directory selectors as you want.
		{
			"file": "[Path to File]"
		},
		{
			"directory": "[Path to Directory]"
		}
	],
	"platforms": [
		// Remove undesired elements from this array.
		"iOS",
		"macOS",
		"tvOS",
		"visionOS"
	]
}
Add a downloader extension swift · at 10:44 ↗
import BackgroundAssets
import ExtensionFoundation
import StoreKit

@main
struct DownloaderExtension: StoreDownloaderExtension {
	
	func shouldDownload(_ assetPack: AssetPack) -> Bool {
		return true
	}
	
}
Download an asset pack swift · at 11:39 ↗
let assetPack = try await AssetPackManager.shared.assetPack(withID: "Tutorial")

// Await status updates for progress information
let statusUpdates = AssetPackManager.shared.statusUpdates(forAssetPackWithID: "Tutorial")
Task {
	for await statusUpdate in statusUpdates {
		// …
  }
}

// Download the asset pack
try await AssetPackManager.shared.ensureLocalAvailability(of: assetPack)
Receive download status updates in Objective-C objectivec · at 12:22 ↗
#import <BackgroundAssets/BackgroundAssets.h>

@interface ManagedAssetPackDownloadDelegate : NSObject <BAManagedAssetPackDownloadDelegate>

@end

@implementation ManagedAssetPackDownloadDelegate

- (void)downloadOfAssetPackBegan:(BAAssetPack *)assetPack { /* … */ }

- (void)downloadOfAssetPackPaused:(BAAssetPack *)assetPack { /* … */ }

- (void)downloadOfAssetPackFinished:(BAAssetPack *)assetPack { /* … */ }

- (void)downloadOfAssetPack:(BAAssetPack *)assetPack hasProgress:(NSProgress *)progress { /* … */ }

- (void)downloadOfAssetPack:(BAAssetPack *)assetPack failedWithError:(NSError *)error { /* … */ }

@end
Attach the delegate in Objective-C objectivec · at 12:29 ↗
static void attachDelegate(ManagedAssetPackDownloadDelegate *delegate) {
	[[BAAssetPackManager sharedManager] setDelegate:delegate];
}
Cancel an asset-pack download swift · at 12:33 ↗
let statusUpdates = AssetPackManager.shared.statusUpdates(forAssetPackWithID: "Tutorial")
for await statusUpdate in statusUpdates {
	if case .downloading(_, let progress) = statusUpdate {
		progress.cancel()
	}
}
Use an asset pack swift · at 12:41 ↗
// Read a file into memory
let videoData = try AssetPackManager.shared.contents(at: "Videos/Introduction.m4v")

// Open a file descriptor
let videoDescriptor = try AssetPackManager.shared.descriptor(for: "Videos/Introduction.m4v")
defer {
	do {
		try videoDescriptor.close()
	} catch {
		// …
	}
}
Remove an asset pack swift · at 13:56 ↗
// Remove the asset pack
try await AssetPackManager.shared.remove(assetPackWithID: "Tutorial")

// Redownload the asset pack
let assetPack = try await AssetPackManager.shared.assetPack(withID: "Tutorial")
try await AssetPackManager.shared.ensureLocalAvailability(of: assetPack)
Info.plist xml · at 14:53 ↗
<key>BAAppGroupID</key>
<string>group.com.naturelab.thecoast</string>
<key>BAHasManagedAssetPacks</key>
<true/>
<key>BAUsesAppleHosting</key>
<true/>

Resources