Add the AppBox SDK to your development, ad-hoc or in-house (enterprise) iOS app and it tells whoever is running an old build that a newer one is ready — from the same AppBox upload you already do.
Every AppBox upload writes an appinfo.json next to the build and gives you one link to share. The SDK reads that same file, compares the published build against the one running, and offers the install page when there is something newer. No account, no extra service, no analytics.
- iOS 15.0 or later
- Xcode 16 or later (Swift 6 tools)
- AppBox for Mac to publish the builds
The SDK ships as a Swift package. CocoaPods and Carthage are no longer supported — see Migrating from 1.x.
File ▸ Add Package Dependencies…, enter https://github.com/getappbox/AppBox-iOS-SDK.git, and add AppBoxSDK to your app target.
dependencies: [
.package(url: "https://github.com/getappbox/AppBox-iOS-SDK.git", from: "4.0.0")
],
targets: [
.target(name: "YourApp", dependencies: [
.product(name: "AppBoxSDK", package: "AppBox-iOS-SDK")
])
]Upload a build with AppBox and keep the same link for all future builds turned on — Keep same link — so one link keeps pointing at your newest build. AppBox then gives you a short link like https://appbox.me/AbCdEf. That is the link the SDK watches.
Any of these work, so paste whichever you have:
| Link | Example |
|---|---|
| Short link | https://appbox.me/AbCdEf |
| Install page link | https://web.getappbox.com?url=/scl/fi/…/appinfo.json?rlkey=… |
Dropbox share link of appinfo.json |
https://www.dropbox.com/scl/fi/…/appinfo.json?rlkey=… |
| Legacy app update key | oge15hcy8nhw9q3 |
Without keep-same-link every upload gets its own link, so a build already on a device keeps watching the link it shipped with and never sees the next one.
import AppBoxSDK
@main
struct YourApp: App {
init() {
AppBox.start(link: "https://appbox.me/AbCdEf")
}
var body: some Scene {
WindowGroup { ContentView() }
}
}Or from a UIApplicationDelegate:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
AppBox.start(link: "https://appbox.me/AbCdEf")
return true
}That is the whole integration. The SDK checks at launch and again whenever the app returns to the foreground, and shows an alert when a newer build is published.
AppBox.start(
link: "https://appbox.me/AbCdEf",
configuration: AppBoxConfiguration(alertStyle: .optional, comparison: .versionAndBuild))| Option | Default | What it does |
|---|---|---|
alertStyle |
.skippable |
.forced offers only Update, .optional adds Next Time, .skippable adds Skip This Version. |
comparison |
.version |
.version compares CFBundleShortVersionString only; .versionAndBuild also compares CFBundleVersion, so a rebuild of the same version counts. |
checksOnForeground |
true |
Check again when the app comes back to the foreground. |
minimumCheckInterval |
60 |
Shortest gap, in seconds, between two automatic checks. |
presentsAlert |
true |
Set false to show your own UI from updateHandler. |
serviceBaseURL |
install.getappbox.com |
The AppBox install service that serves appinfo.json. Set nil to read the share link straight from Dropbox, or point it at your own install-helper. |
isLoggingEnabled |
true in debug |
Logs to the unified logging system under the com.getappbox.sdk subsystem. |
Version and build numbers are compared component by component, so 1.10 is newer than 1.9, and 1.0 and 1.0.0 are the same build.
Turn the built-in alert off and handle the update yourself:
AppBox.start(link: link, configuration: AppBoxConfiguration(presentsAlert: false))
AppBox.shared.updateHandler = { update in
print("\(update.name) \(update.displayVersion) is available")
AppBox.shared.openInstallPage(for: update)
}Or check on demand — this never shows UI and returns nil when there is nothing newer:
if let update = try await AppBox.checkForUpdate() {
// update.version, update.build, update.installURL, update.uploadDate,
// update.buildType, update.fileSizeMB, update.minimumOSVersion
}To watch what the user chose:
AppBox.shared.alertActionHandler = { action, update in
// .update, .later or .skip
}AppBox.resetSkippedBuild() forgets a skipped build so it is offered again, AppBox.stop() ends foreground checking, and AppBox.sdkVersion reports which SDK a build shipped with.
Example/ is a small SwiftUI app with the SDK linked through SPM, plus two ways to publish it — Example/Scripts/upload.sh, which drives appboxcli directly, and fastlane lanes using the AppBox fastlane plugin. Either one gives you the whole build ▸ upload ▸ auto-update loop in one project. See Example/README.md.
1.x shipped as a CocoaPods pod and a Carthage framework. Both are gone; the SDK is a Swift package. Remove pod 'AppBoxSDK' or the getappbox/AppBox-iOS-SDK Cartfile entry and add the package instead.
AppBox.start(key:) addressed Dropbox's legacy /s/<key>/ share links, which new uploads no longer use, and it made you dig the key out of a URL by hand. Pass the link AppBox gives you instead:
// 1.x
AppBox.start(key: "oge15hcy8nhw9q3", alertType: .skip, checkVersionOnly: true)
// 4.x
AppBox.start(
link: "https://appbox.me/AbCdEf",
configuration: AppBoxConfiguration(alertStyle: .skippable, comparison: .version)
)The old symbols still compile, with deprecation warnings pointing at the replacements:
| 1.x | 4.x |
|---|---|
AppBox.start(key:alertType:checkVersionOnly:) |
AppBox.start(link:configuration:) |
AppBox.Default |
AppBox.shared |
AlertType / .force .option .skip |
AppBoxAlertStyle / .forced .optional .skippable |
AlertAction / .appBox .nextTime |
AppBoxAlertAction / .update .later |
checkVersionOnly: Bool |
comparison: .version / .versionAndBuild |
The minimum deployment target moves from iOS 10 to iOS 15.
Nothing happens. Turn logging on (it is on by default in debug builds) and watch the console, or filter Console.app by the com.getappbox.sdk subsystem. Every skipped check says why.
"is not an AppBox install link". The link isn't one of the four forms in the table above. Check you copied the install link and not the IPA or manifest link — the SDK needs the one that ends in appinfo.json.
The alert never comes back after a new upload. The upload has to reuse the same link. Upload with keep-same-link on, or with the fastlane plugin's keep_same_link: true.
A build was skipped by mistake. AppBox.resetSkippedBuild(), or reinstall.
Any contribution is more than welcome, through pull requests and issues on GitHub.
Please post bugs to the issue tracker, including a description of what is not working.
MIT — see LICENSE.