Load asset definitions from remote JSON files hosted on a CDN or server into CE.SDK’s asset library.
Remote asset loading lets you host asset definitions on a CDN or server and load them into CE.SDK at runtime. This keeps asset management separate from your app, so you can update the available assets without shipping a new build. engine.asset.addLocalAssetSourceFromJSON(_:) loads a manifest from a URL, and the string overload loads one you already have in memory.
Setup#
Create a scene and a page so there is something to apply assets to.
let scene = try engine.scene.create()let page = try engine.block.create(.page)try engine.block.setWidth(page, value: 800)try engine.block.setHeight(page, value: 600)try engine.block.appendChild(to: scene, child: page)JSON Manifest Structure#
A manifest declares a version, a source id, and an assets array. Each asset carries an id, localized labels, and a meta object with the URIs and block type.
{ "version": "2.0.0", "id": "my.remote.images", "assets": [ { "id": "sample_image", "label": { "en": "Sample Image" }, "meta": { "uri": "{{base_url}}/images/sample.jpg", "thumbUri": "{{base_url}}/thumbnails/sample.jpg", "blockType": "//ly.img.ubq/graphic", "fillType": "//ly.img.ubq/fill/image", "mimeType": "image/jpeg" } } ]}The id becomes the asset source identifier you pass to every other Asset API call. Each asset’s meta holds the full-size uri, the thumbUri, the blockType to create when applied, the fillType to attach, and the mimeType. The {{base_url}} placeholder resolves against the manifest’s location or a base path you provide.
Loading Assets from a Remote URL#
Pass the manifest’s URL to the async addLocalAssetSourceFromJSON(_:) overload. It fetches and parses the file and returns the source ID from the manifest’s id field. CE.SDK resolves {{base_url}} placeholders against the manifest’s parent directory. Here baseURL is the location where your asset files are hosted.
let imageSourceID = try await engine.asset.addLocalAssetSourceFromJSON( baseURL.appendingPathComponent("ly.img.image/content.json"),)print("Loaded source:", imageSourceID)In production you pass a fully-qualified URL pointing at your CDN or server:
let baseURL = URL(string: "https://cdn.example.com/assets")!let sourceID = try await engine.asset.addLocalAssetSourceFromJSON( baseURL.appendingPathComponent("my-source/content.json"),)print("Loaded source:", sourceID)Loading Assets from a JSON String#
When you already have the manifest content — for example from an API response or a configuration value — use the synchronous string overload. When the manifest contains absolute URLs, no base path is needed.
let absoluteImageURL = baseURL .appendingPathComponent("ly.img.image/images/sample_1.jpg") .absoluteStringlet manifestJSON = """{ "version": "2.0.0", "id": "my.remote.images", "assets": [ { "id": "sample_image", "label": { "en": "Sample Image" }, "meta": { "uri": "\(absoluteImageURL)", "thumbUri": "\(absoluteImageURL)", "blockType": "//ly.img.ubq/graphic", "fillType": "//ly.img.ubq/fill/image", "mimeType": "image/jpeg" } } ]}"""let stringSourceID = try engine.asset.addLocalAssetSourceFromJSON(manifestJSON)print("Loaded source:", stringSourceID)Customizing the Base Path#
When the manifest uses {{base_url}} placeholders for relative paths, pass a basePath so CE.SDK can resolve them against your hosting location.
let hostedManifest = """{ "version": "2.0.0", "id": "my.remote.images.hosted", "assets": [ { "id": "sample_image", "label": { "en": "Sample Image" }, "meta": { "uri": "{{base_url}}/ly.img.image/images/sample_1.jpg", "thumbUri": "{{base_url}}/ly.img.image/images/sample_1.jpg", "blockType": "//ly.img.ubq/graphic", "fillType": "//ly.img.ubq/fill/image", "mimeType": "image/jpeg" } } ]}"""let hostedSourceID = try engine.asset.addLocalAssetSourceFromJSON( hostedManifest, basePath: baseURL.absoluteString,)print("Loaded source:", hostedSourceID)Verifying Loaded Assets#
Call findAssets(sourceID:query:) to query a loaded source. This confirms the manifest was parsed and the assets are available.
let results = try await engine.asset.findAssets( sourceID: "my.remote.images", query: .init(query: nil, page: 0, perPage: 10),)print("Found assets:", results.total)Applying Remote Assets#
Use apply(sourceID:assetResult:) to add an asset from a loaded source to the scene. The engine downloads the underlying media when it is needed and returns the ID of the created block.
let hostedAssets = try await engine.asset.findAssets( sourceID: "my.remote.images.hosted", query: .init(query: nil, page: 0, perPage: 10),)if let asset = hostedAssets.assets.first { let blockID = try await engine.asset.apply(sourceID: "my.remote.images.hosted", assetResult: asset) print("Applied asset to block:", blockID as Any)}Listing Asset Sources#
Call findAllSources() to list the IDs of every registered asset source.
let sources = engine.asset.findAllSources()print("Registered sources:", sources)Removing Asset Sources#
Call removeSource(sourceID:) to remove a source you no longer need, freeing its assets from memory.
try engine.asset.removeSource(sourceID: "my.remote.images")Error Handling#
These methods throw on failure. The URL overload can fail on network errors or a missing file; both overloads fail on malformed JSON. Wrap calls in a do/catch block to handle these cases.
do { let sourceID = try engine.asset.addLocalAssetSourceFromJSON("{ not valid json }") print("Loaded source:", sourceID)} catch { print("Failed to load asset source:", error.localizedDescription)}API Reference#
Methods#
| Method | Description |
|---|---|
engine.asset.addLocalAssetSourceFromJSON(_:) |
Load asset definitions from a JSON file URL. Returns the source ID. |
engine.asset.addLocalAssetSourceFromJSON(_:basePath:) |
Load asset definitions from a JSON string, resolving {{base_url}} placeholders against basePath. Returns the source ID. |
engine.asset.findAssets(sourceID:query:) |
Query the assets in a loaded source. |
engine.asset.apply(sourceID:assetResult:) |
Apply an asset to the scene, creating a block. |
engine.asset.findAllSources() |
List the IDs of all registered asset sources. |
engine.asset.removeSource(sourceID:) |
Remove a loaded asset source. |
Next Steps#
- Assets — How asset sources and assets fit together.
- Serve Assets From Your Server — Host the asset files behind a manifest on your own server or CDN.
- Integrate a Custom Asset Source — Provide assets dynamically with a custom
AssetSourceimplementation.