Skip to content

iOS SDK

Install SeatLayer iOS 0.3.4 and use the complete SwiftUI/UIKit picker, branded components, a custom native layout, or the preserved raw SeatLayerView.

Updated View as Markdown

SeatLayer iOS 0.3.4 ships a complete native buyer picker for SwiftUI and UIKit. Native components own the buyer journey, and the same package preserves the raw SeatLayerView for applications that own every surrounding control.

Install with Swift Package Manager

In Xcode, choose File → Add Package Dependencies and enter:

https://github.com/seatlayer/seatlayer-ios.git

Select exact version 0.3.4, or declare it in a manifest:

Package.swiftswift
dependencies: [
    .package(
        url: "https://github.com/seatlayer/seatlayer-ios.git",
        exact: "0.3.4"
    )
]

Add the SeatLayer product to the app target, then import SeatLayer.

SwiftUI quick start

TicketPicker.swiftswift
import SeatLayer
import SwiftUI

struct TicketPicker: View {
    let event: String

    var body: some View {
        SeatLayerPicker(
            configuration: SeatLayerConfiguration(
                event: event,
                publicKey: "<YOUR_PUBLIC_KEY>",
                maxSelection: 8,
                locale: "en",
                currency: "USD"
            ),
            onCheckout: { handoff in
                try await checkoutBackend.begin(holdId: handoff.holdId)
            }
        )
    }
}

The ready picker covers loading, live inventory, prices and accessibility, venue/floor/section navigation, confirmation and ticket tiers, GA/table quantities, cart and hold state, expiry recovery, 2D/3D and panorama chrome, and one typed checkout handoff.

UIKit quick start

UIKit hosts the same component tree:

TicketPickerViewController.swiftswift
let picker = SeatLayerPickerViewController(
    configuration: SeatLayerConfiguration(
        event: "<YOUR_EVENT_KEY>",
        publicKey: "<YOUR_PUBLIC_KEY>",
        currency: "USD"
    ),
    onCheckout: { handoff in
        try await checkoutBackend.begin(holdId: handoff.holdId)
    },
    onClose: {
        navigationController?.popViewController(animated: true)
    }
)

Call picker.handleBack() before popping the host route. It consumes the picker’s prompt → cart → confirmation → section → venue ladder first. updateAppearance(theme:themeMode:strings:styles:) changes presentation in place without rebuilding the picker or losing camera, selection, or hold state.

Public and private inventory

The examples use a publishable key for Public inventory. For login-gated, presale, partner, channel, or other private inventory, omit publicKey and provide renewable buyer access:

var configuration = SeatLayerConfiguration(
    event: "ev_private",
    currency: "USD"
)

configuration.buyerAccessTokenProvider = { context in
    try await buyerBackend.mintSeatLayerAccess(reason: context.reason)
}

Mint the native buyer-access session on your backend through buyer access sessions, return only its short-lived token to the provider, and treat SDK access details as opaque. Tokens stay in memory and never belong in the binary, URL, logs, analytics, or persistent state.

Choose an integration level

Path API Your application owns
Ready SwiftUI SeatLayerPicker Configuration, callbacks, containing route
Ready UIKit SeatLayerPickerViewController Navigation container and dismissal
Branded picker Theme, strings, options, styles, builders Brand and selected complete parts
Custom SwiftUI SeatLayerPickerScope + public views Entire SwiftUI hierarchy
Custom UIKit SeatLayerPickerMapView or SeatLayerPickerMapViewController + controller Entire UIKit hierarchy
Raw map SeatLayerView Every buyer surface and hold transition

The native-picker paths retain one controller, one presentation model, ordered inventory actions, supported-feature checks, lifecycle recovery, and the same secure checkout handoff.

Explore customization and the component catalogue.

Checkout and hold ownership

The app selects and temporarily holds inventory. Your trusted backend inspects and books after payment or order validation.

  1. onCheckout receives one SeatLayerPickerCheckoutHandoff.
  2. Send only its opaque holdId and normal order context to the backend.
  3. Inspect the hold and calculate the price from trusted server data.
  4. Charge through your existing payment provider.
  5. Reuse the same bookingRef for safe retries.

Ordinary picker state deliberately omits holdId. Before a successful handoff the picker owns the hold, so a confirmed close may release it. After your callback accepts the handoff, the host owns booking, rejection/release, or expiry. If the callback throws, the SDK rejects only that exact handoff and keeps the buyer in a recoverable picker state.

Read holds and secure checkout before wiring payment.

Application and SDK ownership

Native SwiftUI/UIKit owns SeatLayer SDK owns
Header, filters, floor/section navigation, confirmation, tiers/quantities, cart, hold state, checkout, loading/errors, Test Mode, required attribution, Back and adaptive presentation Seats, labels, geometry, hit testing, pan/pinch, venue camera, authored 3D, and panorama pixels
Dynamic Type, VoiceOver, safe areas, scene lifecycle, native haptics and presentation Authoritative inventory state and supported map capabilities

Changing native presentation never creates a second map. The buyer keeps the same camera, selection, and hold state.

Lifecycle and recovery

The ready SwiftUI picker observes scenePhase; the UIKit host observes application notifications. On foreground they report lifecycle state, consume lost-inventory or hold-lapse truth, optionally refresh availability, and synchronize before accepting another buyer action.

SeatLayerPickerOptions(refreshOnResume: false) skips only the optional explicit refresh. Authoritative lifecycle state is still reconciled. announceHoldLapse: false keeps reconciliation but leaves the visible message to the host. A custom host calls controller.lifecycle, controller.refreshAvailability(), and controller.synchronize().

SeatLayerPicker.prewarm() is an optional API that prepares the picker before navigation:

Task { try await SeatLayerPicker.prewarm() }

Prewarm contains no event, public key, buyer token, or hold and does not start a buyer session.

Layout requirement

Give the picker or map a definite height or a full-screen parent. Do not place the venue map in a SwiftUI ScrollView, List, or UIKit UIScrollView; the canvas owns pan, pinch, 3D, and panorama gestures.

Test Mode and attribution

Test Mode follows authoritative event state and must remain visible. The three-bar Powered by SeatLayer mark appears at the safe bottom-right edge when required by the SeatLayer account configuration. Client-side options, styles, and builders cannot override that setting.

Run the tagged example

git clone --branch v0.3.4 --depth 1 https://github.com/seatlayer/seatlayer-ios.git
cd seatlayer-ios
xcodebuild -scheme SeatLayer -destination 'generic/platform=iOS'
xcodebuild -project Example/SeatLayerDemo.xcodeproj \
  -scheme SeatLayerDemo -destination 'generic/platform=iOS Simulator'

The UIKit example exercises the complete picker. Validate SwiftUI/UIKit, Dynamic Type, VoiceOver, rotation, foreground recovery, interactive dismissal, tiers, 3D/panorama, checkout rejection, Test Mode, and attribution on supported physical devices before rollout.

Product scope

iOS 0.3.4 accepts one published Event per picker. Native Performance Group and Season configuration is not part of this release.

Next steps

Navigation

Type to search…

↑↓ navigate↵ selectEsc close