Quick start¶
This page shows a minimal end-to-end integration: construct the client, check for an update, and install it. It assumes you have already added the package and have an app key and app secret from your channel configuration.
Construct the client¶
AppGantryUpdates is a Swift actor. Create one with an
AppGantryConfiguration:
import AppGantrySDK
let updates = AppGantryUpdates(
configuration: AppGantryConfiguration(
baseURL: URL(string: "https://api.appgantry.com/sdk/v1")!,
appKey: "<your-app-key>",
appSecret: "<your-app-secret>"
)
)
You typically construct this once and hold onto it (for example on a view model or an app-level object).
Check, prompt, install¶
// currentVersion / currentBuild default to the host bundle's
// CFBundleShortVersionString and CFBundleVersion.
let info = try await updates.checkForUpdate()
if info.updateAvailable {
let metadata = try await updates.appMetadata()
// Show your prompt using metadata.name, info.latestVersionName,
// and info.releaseNotes. When the user confirms:
let opened = try await updates.beginInstall(for: info)
if opened, let releaseId = info.releaseId {
try await updates.reportInstall(releaseId: releaseId, state: .installing)
}
}
beginInstall(for:) returns false when the update has no iOS
over-the-air manifest; handle that case (for example by falling back to
a direct download on non-iOS
platforms).
What happened on first use¶
The first call that talks to the backend (here, checkForUpdate())
enrolls the install: it exchanges your app secret for a scoped,
revocable update token and persists it in the Keychain. You do not call
enroll() yourself unless you want to. If the token is later rejected,
the SDK re-enrolls transparently and retries once. See
Tokens and errors.
Mandatory updates¶
info.isMandatory is true when the release must be installed. Your UI
should not let the user dismiss a mandatory update. The built-in
UpdatePromptView hides its "Later" button
automatically in that case.
Use the built-in prompt¶
Instead of building your own UI, you can render the shipped SwiftUI view:
let metadata = try await updates.appMetadata()
let icon = try await updates.iconData(for: metadata)
let content = UpdatePromptContent(update: info, metadata: metadata, iconData: icon)
UpdatePromptView(
content: content,
onInstall: { Task { try await updates.beginInstall(for: info) } },
onLater: { /* dismiss */ }
)
See The update prompt for the full detail.
When it doesn't work¶
The failures that catch people out on a first integration, in the order they show up:
| Symptom | Cause | Fix |
|---|---|---|
SDKError.notConfigured on construction |
An empty app key or app secret | Copy both from the channel's SDK app. See Configuration |
The first call throws a 401 |
The app secret is wrong or has been revoked. The /sdk/v1 surface answers a uniform 401 for every credential problem, so the status alone won't tell you which |
Re-check the secret; if it was revoked, create a new SDK app. See Every failure is the same 401 |
info.updateAvailable is false with a newer build uploaded |
The build wasn't published into this SDK app's channel. Uploading is not releasing | Publish the build into that channel as a release |
beginInstall(for:) returns false |
No iOS over-the-air manifest for that release | Fall back to a direct download |
| The install begins and the app icon greys out | The device isn't in the provisioning profile the build was signed with | Enroll the device, regenerate the profile, re-sign, re-upload |
| Everything works in the simulator and nothing works on device | Network policy, or the device can't reach the API | Check HTTPS access to api.appgantry.com from the device |
Anything not on that list is almost certainly a typed SDKError you can
switch on — see Tokens & errors.
Next¶
- Configuration: the app key, app secret, and base URL.
- Installing updates: over-the-air and direct download, and the signing requirements.
- Tokens and errors: error handling and the token lifecycle.