Search Docs
Loading...
Skip to content

Import Remote Assets

Load asset definitions from remote JSON files hosted on a CDN or server into CE.SDK’s asset library.

10 mins
estimated time
GitHub

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")
.absoluteString
let 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#