macOS SDK (Swift)
The licensemanager-swift package does the whole integration for a native Mac app, in SwiftUI or AppKit: it validates the key the customer enters, computes a stable machine fingerprint, stores the key and the license token in the Keychain, verifies the token offline, renews it in the background, and tells your app, at any time, in one state, whether it should unlock.
MyApp.swift
import LicenseManagerKit
import SwiftUI
let licenseManager = try! LicenseManager(
productID: "x7Kp2QaZ",
publicKey: """
-----BEGIN PUBLIC KEY-----
MCowBQYDK2VwAyEA…
-----END PUBLIC KEY-----
"""
)
@main
struct MyApp: App {
@StateObject private var license = LicenseObserver(manager: licenseManager)
var body: some Scene {
WindowGroup {
// .active, .missingKey, .expired…
if license.state == .active { ContentView() } else { ActivationView() }
}
.environmentObject(license)
}
}
What the SDK does
| Validates on every launch | When online, the stored key is validated again on each launch, so an expired license or a deactivated machine is noticed right away. With a valid stored token, it runs in the background, without delaying launch. See validation and renewal. |
| Works offline | When LicenseManager can’t be reached, the app keeps running on the stored token until it expires. See working offline. |
| Renews in the background | The key is validated again before the token expires, even across sleep. Transient failures are retried, and while offline, the SDK keeps trying with a backoff. |
| Locks only when it should | Only the four errors that say something about the license lock the app. A network error, a 500 or a 402 never do. |
| Detects clock tampering | A clock set back to keep using an expired token is detected while offline. See clock tampering. |
| Fingerprints the Mac | From the hardware UUID and a random id stored in the Keychain, specific to your product. See machine fingerprint. |
| Stores secrets safely | In the Keychain, with a file fallback. Development builds never trigger keychain prompts. See stored data. |
| Fits SwiftUI | LicenseObserver publishes the license to your views. LicenseManager is Sendable, with async methods and typed errors. See SwiftUI and AppKit. |
| Sandbox friendly | It spawns no process and only needs outgoing connections: it works in the App Sandbox, with the hardened runtime, notarized. See sandbox and distribution. |
| Compatible with Electron and Tauri | Same Keychain items, same files, same fingerprint: an app moving from Electron or Tauri to Swift keeps its activations. See migrating. |
Requirements
- macOS 13 Ventura or later, and Swift 6 (Xcode 16 or later).
- Your product’s id and your organization’s public key, from the Security page. See what you need.
- In a sandboxed app, the Outgoing Connections (Client) capability.
The package has no dependencies: it only uses Apple’s frameworks, CryptoKit, Security, IOKit and Foundation.
How it works
The pages of this section
- Installation and setup: add the package, create the
LicenseManager, and every option. - Activating a license: the activation screen,
setLicenseKey(_:)and its errors. - License states: what each state means and what your app should show.
- SwiftUI and AppKit:
LicenseObserver, gating features, and AppKit apps. - Validation and renewal: when the SDK validates, what it sends, and how to tune it.
- Working offline: the fallback on the stored token, retries and versions.
- Clock tampering: how a clock set back is detected.
- Machine fingerprint: how the Mac is identified, and how to override it.
- Stored data: what’s stored, where, and how to reset it.
- Sandbox and distribution: entitlements, notarization, and the Mac App Store.
- Migrating from Electron or Tauri: keep your customers’ activations.
- API reference: every type, property and method.
The API reference generated from the source is on the Swift Package Index .
Build your integration against a test product first: its keys start with TEST-, and nothing you do there touches your real customers. See development and release builds.