← Docs
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.