> ## Documentation Index
> Fetch the complete documentation index at: https://docs.clariodesk.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Swift quickstart

> Native in-app support for iOS apps: one SPM package, a live ticket thread, no backend code on your side.

The ClarioDesk Swift SDK is the native iOS expression of the same contract as
the [Flutter](/flutter/quickstart) and [React Native](/react-native/quickstart)
SDKs: device-is-identity auth, live updates over Centrifugo/SSE, attachments,
CSAT, bug reports, and push — as an actor engine with `AsyncStream` reads and a
SwiftUI prebuilt UI.

## Install

Add the package in Xcode (**File → Add Package Dependencies…**) or in
`Package.swift`:

```swift theme={null}
.package(url: "https://github.com/clariodesk/clariodesk-swift", from: "0.1.1")
```

Link the `ClarioDesk` product (headless), and `ClarioDeskUI` too if you want
the prebuilt screens. Requires iOS 16+; the package is Swift 6 and consumable
from Swift 5.x hosts.

## Initialize

`initialize` is synchronous and fire-and-forget — no `await`. The first launch
generates the Secure Enclave device key and registers the device; later
launches reuse the stored key with no network call.

```swift theme={null}
import ClarioDesk

@main
struct MyApp: App {
  init() {
    ClarioDesk.initialize(.init(apiKey: "pk_live_…"))
  }

  var body: some Scene {
    WindowGroup { ContentView() }
  }
}
```

(UIKit hosts call the same line from
`application(_:didFinishLaunchingWithOptions:)`.)

## Identify the user

Call this after your own auth knows who the user is. It's optional, pure
metadata. See [lifecycle](/swift/lifecycle) for the four events you should
wire (especially case 1, which covers users who were logged in before you
installed the SDK).

```swift theme={null}
try await ClarioDesk.identify(
  externalId: user.id,
  email: user.email,
  traits: ["plan": "pro"]
)
```

## File a ticket

```swift theme={null}
let (ticket, _) = try await ClarioDesk.createTicket(
  subject: "Upload broken",
  body: "Tapping upload does nothing."
)
```

## Stream the inbox & a thread

Reactive reads are replay-last `AsyncStream`s: a new iterator immediately gets
the current value, then live updates.

```swift theme={null}
struct InboxView: View {
  @State private var tickets: [Ticket] = []

  var body: some View {
    List(tickets) { ticket in
      Text(ticket.subject)
    }
    .task {
      do {
        for try await latest in ClarioDesk.tickets { tickets = latest }
      } catch { /* render a retry state */ }
    }
  }
}

// A single thread:
for try await messages in ClarioDesk.messages(ticketId: ticket.id) {
  render(messages)
}
```

UIKit hosts use the closure variants instead of `for await`:

```swift theme={null}
let sub = ClarioDesk.subscribeTickets { result in
  if case .success(let tickets) = result { render(tickets) }
}
// sub.cancel() when done
```

## Send a reply

```swift theme={null}
_ = try await ClarioDesk.sendMessage(
  ticketId: ticket.id,
  body: "Still happening on 1.4.2"
)
```

## Run the example app

The package repo ships `Examples/SwiftUIExample`, a runnable SwiftUI host:

```bash theme={null}
cd Examples/SwiftUIExample
xcodegen generate
xcodebuild -scheme ClarioDeskSwiftUIExample \
  -destination 'generic/platform=iOS Simulator' build
```

<CardGroup cols={2}>
  <Card title="Lifecycle integration" icon="user-check" href="/swift/lifecycle">
    Wire login, launch, logout, and user-switch.
  </Card>

  <Card title="Prebuilt UI" icon="layout-panel-left" href="/swift/prebuilt-ui">
    Skip building the UI. Open a themeable inbox in one call.
  </Card>
</CardGroup>
