Amba

iOS Swift SDK

Swift quickstart for the Amba SDK — Swift Package Manager install, Amba.configure, Amba.events.track, Sign in with Apple, and APNs push registration in under 10 minutes.

Amba for iOS is a Swift Package distributed via layers/amba-sdk-ios. Single import; everything else in this guide assumes you've added it to your target.

Supported platforms: iOS 14+, macOS 12+, tvOS 14+, watchOS 7+.

1. Install via Swift Package Manager

In Xcode

File → Add Package Dependencies… → enter:

https://github.com/layers/amba-sdk-ios

Pick the dependency rule Up to Next Major with 1.0.0, then add the Amba product to your app target.

In Package.swift

// Package.swift
let package = Package(
    name: "MyApp",
    platforms: [.iOS(.v14)],
    dependencies: [
        .package(url: "https://github.com/layers/amba-sdk-ios", from: "1.0.0"),
    ],
    targets: [
        .target(
            name: "MyApp",
            dependencies: [
                .product(name: "Amba", package: "amba-sdk-ios"),
            ]
        ),
    ]
)

The package's .binaryTarget resolves to a prebuilt AmbaCoreFFI.xcframework.zip published as a release asset on each tagged version — first build downloads ~12 MB, subsequent builds use Xcode's cache.

2. Configure at app launch

// MyAppApp.swift
import SwiftUI
import Amba
 
@main
struct MyAppApp: App {
    init() {
        do {
            try Amba.configure(apiKey: "amb_dev_ck_XXXX")
        } catch {
            print("amba: failed to configure — \(error)")
        }
    }
 
    var body: some Scene {
        WindowGroup { ContentView() }
    }
}

For UIKit, do the same in application(_:didFinishLaunchingWithOptions:):

import UIKit
import Amba
 
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    func application(_ application: UIApplication,
                     didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        do {
            try Amba.configure(apiKey: "amb_dev_ck_XXXX")
        } catch {
            print("amba: failed to configure — \(error)")
        }
        return true
    }
}

Don't ship a hard-coded key. Inject AMBA_API_KEY via your .xcconfig, an Info.plist build-setting, or arkana — and reference it via Bundle.main.object(forInfoDictionaryKey:) or your secrets framework.

3. First sign-in (anonymous + Sign in with Apple)

Amba.events.track is authenticated server-side — the request needs a session token. Sign in (anonymously is fine) before the first track call:

import Amba
 
// Anonymous — minted on first launch, restored from Keychain on subsequent ones.
Task {
    do {
        let session = try await Amba.auth.signInAnonymously()
        print("signed in:", session.user.id)
    } catch {
        print("sign-in failed:", error)
    }
}

4. First event

Once a session exists, track engagement events:

import Amba
 
Task {
    try await Amba.events.track("app_opened", properties: ["source": "deep_link"])
}

Amba.events.track is async throws — wrap in a Task { } from UI code, or await directly from another async context.

Sign in with Apple

import AuthenticationServices
import Amba
 
final class AppleSignInCoordinator: NSObject, ASAuthorizationControllerDelegate {
    func signIn() {
        let request = ASAuthorizationAppleIDProvider().createRequest()
        request.requestedScopes = [.fullName, .email]
        let controller = ASAuthorizationController(authorizationRequests: [request])
        controller.delegate = self
        controller.performRequests()
    }
 
    func authorizationController(controller: ASAuthorizationController,
                                 didCompleteWithAuthorization authorization: ASAuthorization) {
        guard let credential = authorization.credential as? ASAuthorizationAppleIDCredential,
              let tokenData = credential.identityToken,
              let identityToken = String(data: tokenData, encoding: .utf8) else { return }
 
        Task {
            do {
                let session = try await Amba.auth.signInWithApple(identityToken: identityToken)
                print("signed in:", session.user.id)
            } catch {
                print("Apple sign-in failed:", error)
            }
        }
    }
 
    func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: Error) {
        print("Apple sign-in error:", error)
    }
}

Add the Sign in with Apple capability in Xcode → Signing & Capabilities before the first build.

5. Register for APNs push

import UIKit
import UserNotifications
import Amba
 
extension AppDelegate {
    func registerForPushNotifications() {
        UNUserNotificationCenter.current().requestAuthorization(
            options: [.alert, .badge, .sound]
        ) { granted, _ in
            guard granted else { return }
            DispatchQueue.main.async {
                UIApplication.shared.registerForRemoteNotifications()
            }
        }
    }
 
    func application(_ application: UIApplication,
                     didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        let token = deviceToken.map { String(format: "%02x", $0) }.joined()
        Task {
            do {
                _ = try await Amba.push.register(
                    token: token,
                    platform: .apns,
                    bundleId: Bundle.main.bundleIdentifier
                )
            } catch {
                print("amba: push register failed —", error)
            }
        }
    }
 
    func application(_ application: UIApplication,
                     didFailToRegisterForRemoteNotificationsWithError error: Error) {
        print("amba: APNs registration failed —", error)
    }
}

Add the Push Notifications capability + Background Modes → Remote notifications in Xcode before building. Upload your APNs auth key (or .p8) to the amba console once per bundle ID.

6. First collection insert

The Swift SDK uses Codable for typed reads + writes:

import Amba
 
struct Post: Codable {
    let id: String
    let title: String
    let body: String
    let createdAt: Date
 
    enum CodingKeys: String, CodingKey {
        case id, title, body
        case createdAt = "created_at"
    }
}
 
Task {
    let inserted: Post = try await Amba.collections.insert(
        "posts",
        row: ["title": "Hello amba", "body": "first post from iOS"],
        as: Post.self
    )
 
    let resp: FindResponse<Post> = try await Amba.collections.find(
        "posts",
        options: FindOptions(
            order: [OrderBy(column: "created_at", direction: .desc)],
            limit: 20
        )
    )
    print("got \(resp.data.count) posts")
}

7. AI proxy

import Amba
 
Task {
    let response = try await Amba.ai.anthropic.messages.create(
        request: AiMessageRequest(
            promptSlug: "support_assistant",
            variables: AnyEncodable(["user_query": "How do I cancel?"]),
            maxTokens: 1024
        )
    )
    print(response.content)
}

Construct an AmbaClient directly (testing / multi-tenant)

For tests or multi-tenant apps, instantiate AmbaClient directly instead of using the singleton facade:

import Amba
 
let client = try AmbaClient(apiKey: "amb_dev_ck_XXXX")
try await client.events.track("test_event")

Tests can inject a mock conforming to AmbaCoreFfiProtocol via the internal initializer.

PrivacyManifest

The SDK ships PrivacyInfo.xcprivacy declaring its data-collection categories per Apple's PrivacyManifest spec. App Store review aggregates this with your app's own manifest — you don't need to copy entries from the SDK into yours.

Common pitfalls

  • Amba.configure not called before any other Amba.* access throws AmbaSwiftError.notConfigured. Configure in init of your @main App / application:didFinishLaunchingWithOptions:.
  • XCFramework not building for simulator — the prebuilt xcframework includes simulator + device slices for both arm64 and x86_64. If swift build fails with "no compatible binary for the current platform," your Xcode is older than 15.0 and can't link the new xcframework format — upgrade Xcode.
  • APNs token registered but no delivery — verify the APNs auth key in the amba console matches the bundle ID Xcode signed your app with. The token is valid; the server-side lookup fails 404 if bundle IDs drift.
  • Sign in with Apple identity token expiredcredential.identityToken is short-lived. Always pass it to Amba.auth.signInWithApple immediately; don't cache and reuse.
  • Background task running past app foreground — if Amba.configure was called in a now-deallocated context, the amba core's HTTP client survives but its observer hooks may be invalidated. Always re-check Amba.isAuthenticated before issuing background calls.

See also