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

# Set Up Candid User Research in a UIKit Application

> Configure Candid in AppDelegate or SceneDelegate, attach the overlay to your root view controller, and trigger in-app research sessions.

UIKit apps follow the same configure-then-show pattern as SwiftUI, with one extra step: you must explicitly attach the Candid overlay to a `UIViewController` so the SDK knows where to anchor its research bubble and modal screens. Use `Candid.attachUIKitOverlay(to:)` right after you set your window's root view controller, and call `Candid.register(trigger:)` whenever you want a study to start. (In SDK versions before 0.2.0 this method was named `attachOverlay(to:)`.)

## Configure the SDK

Call `Candid.configure(_:)` once at launch, before your app presents any UI. `AppDelegate.application(_:didFinishLaunchingWithOptions:)` and `SceneDelegate.scene(_:willConnectTo:options:)` are both appropriate places.

```swift theme={null}
import CandidSDK
import UIKit

@main
class AppDelegate: UIResponder, UIApplicationDelegate {
    func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        Candid.configure(
            Candid.Configuration(
                apiKey: "YOUR_API_KEY",
                recordingDuration: 600,
                appearance: Candid.Appearance(
                    primaryColor: "#35C884",
                    font: .system(.rounded)
                )
            )
        )
        Candid.setUserId(AuthSession.current.userId)
        return true
    }
}
```

If your app uses the scene-based lifecycle, configure in `SceneDelegate` instead:

```swift theme={null}
import CandidSDK
import UIKit

class SceneDelegate: UIResponder, UIWindowSceneDelegate {
    var window: UIWindow?

    func scene(
        _ scene: UIScene,
        willConnectTo session: UISceneSession,
        options connectionOptions: UIScene.ConnectionOptions
    ) {
        Candid.configure(
            Candid.Configuration(apiKey: "YOUR_API_KEY")
        )
        Candid.setUserId(AuthSession.current.userId)
        // Attach the overlay after setting up the window, see next section.
    }
}
```

## Attach the overlay

After you assign a root view controller to your `UIWindow`, call `Candid.attachUIKitOverlay(to:)` with that same root controller. The SDK adds a transparent overlay view above your app's interface to host the research bubble and modal screens. The overlay only intercepts touches that land on visible Candid UI; everything else passes through to your app.

```swift theme={null}
func scene(
    _ scene: UIScene,
    willConnectTo session: UISceneSession,
    options connectionOptions: UIScene.ConnectionOptions
) {
    guard let windowScene = scene as? UIWindowScene else { return }

    Candid.configure(
        Candid.Configuration(apiKey: "YOUR_API_KEY")
    )
    Candid.setUserId(AuthSession.current.userId)

    let rootViewController = MainTabBarController()
    let window = UIWindow(windowScene: windowScene)
    window.rootViewController = rootViewController
    window.makeKeyAndVisible()
    self.window = window

    // Attach after the window is visible.
    Candid.attachUIKitOverlay(to: rootViewController)
}
```

<Note>
  Pass your **root** view controller, the one assigned to `window.rootViewController`, not a child, tab, or presented controller. Attaching to a child controller clips the overlay to that controller's view bounds and breaks the layout of the research bubble.
</Note>

## Register a trigger

Call `Candid.register(trigger:)` wherever it makes sense in your app flow. Candid fetches the currently running study from your dashboard and presents it over your content.

<Steps>
  <Step title="From a UIButton action">
    ```swift theme={null}
    @objc private func feedbackButtonTapped() {
        Candid.register(trigger: "feedback")
    }
    ```
  </Step>

  <Step title="In viewDidAppear">
    ```swift theme={null}
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        Candid.register(trigger: "home")
    }
    ```
  </Step>

  <Step title="After a condition">
    ```swift theme={null}
    func onboardingDidComplete() {
        // Existing logic…
        Candid.register(trigger: "onboarding_done")
    }
    ```
  </Step>
</Steps>

## Detach the overlay

Call `Candid.detachUIKitOverlay()` when you no longer need the research UI, for example, when the user logs out or when a particular scene is torn down.

```swift theme={null}
func sceneDidDisconnect(_ scene: UIScene) {
    Candid.detachUIKitOverlay()
}
```

You can re-attach the overlay at any time by calling `Candid.attachUIKitOverlay(to:)` again with a new root controller.

<Tip>
  If your app replaces its root view controller at runtime (for example, switching from an onboarding flow to the main app), call `Candid.detachUIKitOverlay()` before the swap and `Candid.attachUIKitOverlay(to:)` with the new root controller after it.
</Tip>
