Patterns for power users — client-side options, re-edit behavior, error handling, privacy, and accessibility.
Option overrides
Inject or compute options on-device, per suggestion type. Useful when an option list depends on the user's typed input (e.g. dollar amounts, account names) or comes from your own state. The closure receives the text typed against that pill.
AIAutocompleteController.Configuration(apiConfig: .apiKey(.init(apiKey: "pk_v1_your_public_key")),optionOverrides: ["account": { _ in [SuggestionOption(text: "Savings", isTappable: true),SuggestionOption(text: "Checking", isTappable: true)] },"value": { query inlet digits = query.filter(\.isNumber)let amount = digits.isEmpty ? "$100" : "$\(digits)"return [SuggestionOption(text: amount, isTappable: true)]}])
Re-editing completed params
Filled pills stay editable — the full views handle all of this for you:
- Tapping a completed param (or moving the caret inside it) enters re-edit mode and reopens its cached options — no refetch.
- Picking a different option replaces the param's text atomically.
- Deleting through a pill's edge removes the whole param; removeLastParam() does the same programmatically.
Error handling
Every terminal failure reaches onError as a typed AIAutocompleteError — match on the cases you care about.
AIAutocompleteController.Configuration(apiConfig: .apiKey(.init(apiKey: "pk_v1_your_public_key")),onError: { error inswitch error {case .network(let urlError):print("Offline or timed out: \(urlError)")case .http(let status, let message):print("Server returned \(status): \(message ?? "")")case .unauthorized:print("Token rejected twice — re-authenticate")case .tokenProvider(let underlying):print("getAccessToken threw: \(underlying)")default:print("Unexpected: \(error)")}})
Cancelled fetches (superseded by newer keystrokes) are consumed internally and never reach onError. The controller also mirrors the last error on its error property — clear it with dismissError().
Accessibility
The views are built on UIKit text and collection primitives and respect system accessibility settings:
- Dynamic Type: all SDK text scales with the user's setting; option text is clamped at maximumContentSizeCategory.
- Reduce Motion: always wins over the animations token — visual effects stop while the rest of the UI behaves identically.
- Haptics: the promotion tick respects the haptics switch and is independent of animations, so Reduce Motion users keep the tactile cue.