Installing updates¶
Once the user confirms, you install the new build. On iOS this happens over the air; on other platforms, or when you want the raw bytes, you resolve or download the release yourself.
Over-the-air install (iOS)¶
The SDK adds a UIKit-facing method on iOS (not watchOS):
beginInstall(for:) opens the release's itms-services manifest URL
with UIApplication.open, which asks iOS to install the new build in
place. It returns false when the update has no iOS over-the-air
manifest (so there is nothing to open), and true when the install was
handed off to the system.
Under the hood the install uses an itms-services URL of the form:
If you need the manifest URL yourself (for example to open it through your own code path), resolve it directly:
It returns the itms-services URL, or nil if the update has no iOS
manifest. The HTTPS manifest URL carried inside it already includes a
short-lived signed capability token, so treat it as sensitive and
short-lived.
Signing and provisioning requirements¶
Over-the-air install has hard platform requirements that the SDK cannot work around:
- The app must be signed for distribution to your testers: ad-hoc, enterprise/in-house, or another distribution profile that the target device trusts.
- For ad-hoc distribution, the device must be provisioned (its UDID in the provisioning profile).
The SDK cannot install the binary itself
The SDK hands the install off to iOS by opening the manifest URL. It
cannot install the .ipa in-process and cannot observe
SpringBoard's install progress. After beginInstall(for:)
returns, the system UI takes over. Use
reportInstall(...) to record
what your app knows (that an install was started), not to track
SpringBoard.
Direct download¶
For non-iOS platforms, or when you want the bytes yourself instead of the iOS OTA install, resolve a signed URL or download the file:
// A signed URL to the release artifact. No download happens.
public func downloadURL(forRelease releaseId: UUID) async throws -> URL
// Downloads to a temporary file. The caller owns (and should clean up)
// the returned file.
public func downloadRelease(_ releaseId: UUID) async throws -> URL
let signedURL = try await updates.downloadURL(forRelease: info.releaseId!)
let fileURL = try await updates.downloadRelease(info.releaseId!) // you own the file
downloadRelease(_:) returns a temporary file URL that you own:
move it where you need it and delete it when you are done.
Reporting the install lifecycle¶
Record where the install got to. This is optional and is the only data the SDK sends (see Privacy):
public func reportInstall(
releaseId: UUID,
state: InstallState,
errorMessage: String? = nil
) async throws
InstallState is one of downloading, installing, installed, or
failed. Pass errorMessage only on failed:
try await updates.reportInstall(releaseId: releaseId, state: .installing)
// ... later, if your own install flow fails ...
try await updates.reportInstall(
releaseId: releaseId,
state: .failed,
errorMessage: "user cancelled"
)
The models¶
checkForUpdate() returns an UpdateInfo, and appMetadata() returns
an AppMetadata.
public struct UpdateInfo: Codable, Sendable, Equatable {
let updateAvailable: Bool
let alreadyCurrent: Bool
let isMandatory: Bool
let releaseId: UUID?
let platform: Platform?
let latestVersionName: String?
let latestBuildNumber: Int?
let releaseNotes: String?
let sizeBytes: Int?
let releasedAt: Date?
let downloadURL: String? // path relative to /sdk/v1
let iosManifestURL: String? // path relative to /sdk/v1, signed
}
public struct AppMetadata: Codable, Sendable, Equatable {
let name: String
let platform: Platform
let hasRelease: Bool
let latestVersionName: String?
let latestBuildNumber: Int?
let minOSVersion: String?
let iconURL: String?
}
downloadURL and iosManifestURL are paths relative to the /sdk/v1
base; prefer the downloadURL(forRelease:), downloadRelease(_:),
iosInstallURL(for:), and beginInstall(for:) helpers, which resolve
and sign them for you.
Next¶
- The update prompt: what to show before you call
beginInstall(for:). - Tokens and errors: handling failures from these calls.
- API reference: the underlying
/sdk/v1endpoints.