Integration Tiers

Three ways in — the drop-in view, the shared controller with your own input, or the fully headless core.

Tier 1

Full view

AIAutocomplete (SwiftUI) or AIAutocompleteView (UIKit). The SDK owns the input, pills, dropdown, and all state.

Use when: you want autocomplete working in minutes with stock UI.

Tier 2

Your input + SDK dropdown

You own the text field; the SDK renders its dropdown next to it. Wire text through controller.textBinding and float the dropdown with .aiAutocompleteDropdown(_:).

Use when: you have a custom input (rich editor, search bar, existing form field) but want the stock dropdown.

Tier 3

Headless

AIAutocompleteCore only. The @Observable controller exposes all state and actions; you render everything yourself.

Use when: you need full control over rendering on top of the SDK's state machine.

Tier 1 — Full view

One view, no wiring. Lifecycle is automatic — it starts fetching on appear and stops on disappear. Tapping the submit button submits and resets for the next query.

ComposerView.swift
import AIAutocompleteCore
import AIAutocompleteSwiftUI
import SwiftUI
struct ComposerView: View {
@FocusState private var isFocused: Bool
var body: some View {
AIAutocomplete(configuration: .init(
apiConfig: .apiKey(.init(apiKey: "pk_v1_your_public_key")),
onSubmit: { result in print(result.query) }
))
.submitButton {
Image(systemName: "arrow.up")
.font(.system(size: 15, weight: .semibold))
.foregroundStyle(.white)
.frame(width: 32, height: 32)
.background(.black, in: .circle)
}
.focused($isFocused)
.padding()
}
}

submitButton supplies visuals only — the SDK wires the tap to submit + reset. focused bridges the input's first-responder state to a @FocusState binding, in both directions.

UIKit

AIAutocompleteView is the same Tier 1 surface for UIKit. It sizes itself via intrinsicContentSize — pin the edges and let it grow. Set submitButtonView for a custom button, or showsSubmitButton = false to hide it.

ComposerViewController.swift
import AIAutocompleteCore
import AIAutocompleteUIKit
import UIKit
final class ComposerViewController: UIViewController {
private lazy var autocomplete = AIAutocompleteView(
configuration: .init(
apiConfig: .apiKey(.init(apiKey: "pk_v1_your_public_key")),
onSubmit: { result in print(result.query) }
)
)
override func viewDidLoad() {
super.viewDidLoad()
autocomplete.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(autocomplete)
NSLayoutConstraint.activate([
autocomplete.leadingAnchor.constraint(equalTo: view.layoutMarginsGuide.leadingAnchor),
autocomplete.trailingAnchor.constraint(equalTo: view.layoutMarginsGuide.trailingAnchor),
autocomplete.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor)
])
}
}

Tier 2 — Your input, SDK dropdown

Hold the controller yourself (@State), bind your field's text to controller.textBinding, forward focus with setFocused(_:), and float the dropdown over the field with .aiAutocompleteDropdown(_:). The dropdown sizes itself and clamps to the space above the keyboard.

CustomComposer.swift
import AIAutocompleteCore
import AIAutocompleteSwiftUI
import SwiftUI
struct CustomComposer: View {
@State private var controller = AIAutocompleteController(
configuration: .init(apiConfig: .apiKey(.init(apiKey: "pk_v1_your_public_key")))
)
@FocusState private var isFocused: Bool
var body: some View {
VStack(spacing: 12) {
TextField("Create a", text: controller.textBinding)
.textFieldStyle(.roundedBorder)
.focused($isFocused)
.onChange(of: isFocused) { _, focused in
controller.setFocused(focused)
}
.aiAutocompleteDropdown(controller)
Button("Submit") {
controller.submitAndReset()
}
}
.padding()
}
}

Prefer placing the dropdown yourself (e.g. in a stack)? Use the standalone AIAutocompleteDropdown(controller:) view instead of the modifier — same behavior, your layout.

Tier 3 — Headless

Import only AIAutocompleteCore and render from the controller's observable state: segments for the input's text-and-pill spans, filteredOptions for the option list, isDropdownOpen for visibility. Call start() when your UI appears.

HeadlessComposer.swift
import AIAutocompleteCore
import SwiftUI
struct HeadlessComposer: View {
@State private var controller = AIAutocompleteController(
configuration: .init(apiConfig: .apiKey(.init(apiKey: "pk_v1_your_public_key")))
)
var body: some View {
VStack(alignment: .leading, spacing: 8) {
TextField("Create a", text: controller.textBinding)
.onSubmit { controller.submitAndReset() }
if controller.isDropdownOpen {
ForEach(controller.filteredOptions, id: \.text) { option in
Button(option.text) {
controller.selectOption(option)
}
}
}
}
.onAppear { controller.start() }
.onDisappear { controller.stop() }
}
}