Recipe
Swift iOS patterns
Production-ready patterns for integrating Meridian licensing into native iOS apps built with Swift.
Singleton license manager
Centralize license state in a thread-safe singleton. Use a serial dispatch queue to avoid races during validation and renewal.
final class LicenseManager {
static let shared = LicenseManager()
private let queue = DispatchQueue(label: "meridian.license")
private var current: License?
func validate(key: String) async throws -> License {
try await withCheckedThrowingContinuation { cont in
queue.async { /* Meridian REST call */ }
}
}
}Keychain persistence
Store the license key in the iOS Keychain with biometric access control. Never persist keys in UserDefaults or plaintext files.
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: "meridian_key",
kSecAttrAccessControl as String: SecAccessControlCreateWithFlags(
nil, kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
.biometryCurrentSet, nil
)!
]Offline grace window
Cache the last successful validation timestamp and an HMAC-signed grace token. Allow up to 72 hours of offline use before requiring a re-check.
Combine publisher for license state
Expose a Combine publisher so SwiftUI views reactively bind to license validity. Emit on validation, expiry, and revocation.
@Published private(set) var status: LicenseStatus = .unknown
func observe() -> AnyPublisher<LicenseStatus, Never> {
$status.eraseToAnyPublisher()
}Full REST API reference available in the API docs. Swift package coming soon.