๐ Language Selection / Chแปn ngรดn ngแปฏ / ่จ่ช้ธๆ:
๐ฌ๐ง English ย |ย
๐ป๐ณ Tiแบฟng Viแปt ย |ย
๐ฏ๐ต ๆฅๆฌ่ช
AppUpdateKit is an ultra-lightweight, zero-dependency, headless-first Swift Package for evaluating app versions, enforcing Force Updates, presenting Optional Updates (with release notes), and activating Maintenance Mode remotely via microCMS, Raw JSON (GitHub Raw, S3, Cloudflare Workers), or any backend endpoint.
- 100% Headless-First (UI is strictly optional): AppUpdateKit is built as a pure business logic engine (
AppUpdateChecker,AppUpdateEvaluator,AppVersion,AppUpdateConfig). You are never forced to use our UI. All raw models, metadata, version objects, and event streams are exposed so you can render your own custom dialogs, sheets, or bridges (React Native, Flutter). - Zero Third-Party Dependencies: Pure Swift Standard Library (
Foundation,SwiftUI,Combine,UIKit). - O(N) SemVer Normalizer: Vector integer comparator (
"1.2"=="1.2.0"=="1.2.0.0","1.10.0">"1.2.0"), stripping prerelease tags and build metadata. - Fail-Safe by Default: Network errors, timeouts, or corrupt JSON gracefully fallback to
.nonewithout crashing or blocking users. - Full Lifecycle Events & Analytics: Emits granular events (
checkStarted,configFetched,evaluated,presented,userAction,checkFailed) for Firebase, Mixpanel, and custom logging. - Swift 6 & Sendable Compliant: Fully concurrency-safe with
@MainActorsafety and Task deduplication.
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Update Available โ โ โญโโโโโโโโโโโโโฎ โ
โ โ โ โ ๐ โ โ
โ A new version (2.1.0) is available on โ โ โฐโโโโโโโโโโโโโฏ โ
โ the App Store. Would you like to get โ โ Bแบฃn Cแบญp Nhแบญt Mแปi 2.1.0 โ
โ the latest features? โ โ Trแบฃi nghiแปm giao diแปn mแปi vร sแปญa lแปi. โ
โ โ โ โ
โ โ โ โโโ Cรณ gรฌ mแปi: โโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ โ โข โจ Giao diแปn Liquid Glass โ โ
โ โ โ โ โข โก๏ธ Tแปi ฦฐu tแปc ฤแป tแบฃi 40% โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ โ โข ๐ Sแปญa lแปi offline sync โ โ
โ โ ฤแป sau (Later)โโCแบญp nhแบญt(Updateโ โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ โ Cแบญp nhแบญt ngay (Update) โ โ
โ โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ ฤแป sau โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
[ SwiftUI / UIKit Alert ] [ Custom SwiftUI Card Sheet ]
Use pure evaluation logic without touching any UI code:
import AppUpdateKit
let fetcher = AppUpdateFetcher.microCMS(
endpoint: URL(string: "https://your-service.microcms.io/api/v1/app-update")!,
apiKey: "YOUR_API_KEY"
)
// Check update status asynchronously (fail-safe)
let action: AppUpdateAction = await AppUpdateChecker.check(
onEvent: { event in
Analytics.logEvent("app_update_lifecycle", parameters: ["event": "\(event)"])
},
fetcher: fetcher
)
// Handle action in your own custom View, Modal, or Coordinator
switch action {
case .none:
print("App is up-to-date")
case .optionalUpdate(let title, let message, let storeURL, let version, let releaseNotes, let metadata):
MyCustomDialogPresenter.showOptionalUpdate(title: title, version: version?.description, url: storeURL)
case .forceUpdate(let title, let message, let storeURL, let version, let releaseNotes, let metadata):
MyCustomDialogPresenter.showBlockingUpdate(title: title, url: storeURL)
case .maintenance(let title, let message, let metadata):
MyCustomDialogPresenter.showMaintenanceScreen(message: message)
case .custom(let id, let title, let message, let storeURL, _, _, _):
MyCustomDialogPresenter.handleCustomAction(id: id)
}ContentView()
.appUpdateAlert(
action: $updateAction,
configuration: AppUpdateUIConfiguration(
updateButtonTitle: "Update Now",
laterButtonTitle: "Later",
dismissButtonTitle: "OK"
),
onEvent: { event in
print("[AppUpdateKit] Event: \(event)")
}
)ContentView()
.appUpdateSheet(
action: $updateAction,
accentColor: .indigo,
onEvent: { event in
if case .userAction(let action, let choice) = event {
print("User tapped \(choice) for \(action.title ?? "")")
}
}
)class ViewController: UIViewController {
func checkVersion() {
Task { [weak self] in
let action = await AppUpdateChecker.check(fetcher: fetcher)
self?.presentAppUpdate(action: action)
}
}
}| Current Version | Remote Minimum | Remote Latest | Evaluated Action | Application Behavior |
|---|---|---|---|---|
1.0.0 |
2.0.0 |
2.5.0 |
.forceUpdate |
๐จ Blocking update required to proceed |
2.0.0 |
1.5.0 |
2.1.0 |
.optionalUpdate |
๐ก Show update prompt (with "Later" button) |
2.1.0 |
1.5.0 |
2.1.0 |
.none |
โ App is on latest version |
2.1.0.0 |
1.5.0 |
2.1 |
.none |
โ Vector-normalized match |
any |
any |
any (is_maintenance: true) |
.maintenance |
๐ ๏ธ Lock app, show maintenance screen |
1.0.0 |
Network Error (404/500/Timeout) | N/A | .none |
๐ก๏ธ Fail-safe: app functions normally |
| Field ID | Display Name | Type | Description |
|---|---|---|---|
minimum_version |
Minimum Version | Text | Versions below this trigger force update |
latest_version |
Latest Version | Text | Current latest version on App Store |
store_url |
Store URL | Text | App Store or TestFlight link |
is_maintenance |
Is Maintenance | Boolean | System maintenance toggle flag |
title |
Title | Text (Optional) | Custom dialog title |
message |
Message | Multi-line Text (Optional) | Custom explanation message |
release_notes |
Release Notes | Multi-line Text / Array | Bullet list of release notes |
dependencies: [
.package(url: "https://github.com/iletai/AppUpdateKit.git", from: "1.1.0")
]AppUpdateKit is released under the MIT License. Copyright (c) 2026 iletai.