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.gitSelect exact version 0.3.4, or declare it in a manifest:
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
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:
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.
onCheckoutreceives oneSeatLayerPickerCheckoutHandoff.- Send only its opaque
holdIdand normal order context to the backend. - Inspect the hold and calculate the price from trusted server data.
- Charge through your existing payment provider.
- Reuse the same
bookingReffor 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.