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.
import AIAutocompleteCoreimport AIAutocompleteSwiftUIimport SwiftUIstruct ComposerView: View {@FocusState private var isFocused: Boolvar 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.
import AIAutocompleteCoreimport AIAutocompleteUIKitimport UIKitfinal 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 = falseview.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.
import AIAutocompleteCoreimport AIAutocompleteSwiftUIimport SwiftUIstruct CustomComposer: View {@State private var controller = AIAutocompleteController(configuration: .init(apiConfig: .apiKey(.init(apiKey: "pk_v1_your_public_key"))))@FocusState private var isFocused: Boolvar body: some View {VStack(spacing: 12) {TextField("Create a", text: controller.textBinding).textFieldStyle(.roundedBorder).focused($isFocused).onChange(of: isFocused) { _, focused incontroller.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.
import AIAutocompleteCoreimport SwiftUIstruct 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 inButton(option.text) {controller.selectOption(option)}}}}.onAppear { controller.start() }.onDisappear { controller.stop() }}}