# Geolocation

The Geolocation module requests location permission, then captures the precise physical location of the user's device, using its GPS sensor to record coordinates and location fields such as country, state, and city. You can configure whether the user is allowed to skip the step when a location fix is not available.

For an overview of this module and how it works, see [Geolocation](https://developer.incode.com/docs/geolocation-2).

How you use this module depends on your integration pattern. When the app defines the steps in code, you add the module to an `IncdOnboardingFlowConfiguration` as shown below; when the flow is defined in Dashboard, you reference it by ID. See [Integration Approaches](https://developer.incode.com/docs/ios-flow-configuration).

This module requires the `NSLocationWhenInUseUsageDescription` key. See [Add Required Permissions](https://developer.incode.com/docs/setup-ios#add-required-permissions).

**Availability:** All variants.

## Add Geolocation

Add the module with `addGeolocation()`. Geolocation requests location permission at runtime. If the user denies permission, the outcome depends on whether you set the module as skippable. The single parameter is optional; call `addGeolocation()` with no arguments to use the default configuration, which sets the module as not skippable.

```swift
flowConfig.addGeolocation(isSkippable: false)
```

### Example

The example below builds a flow with a non-skippable Geolocation module, registers the delegate, and starts onboarding. The result is delivered through the `onGeolocationCompleted(_:)` delegate callback.

```swift
import IncdOnboarding

final class VerificationCoordinator: IncdOnboardingDelegate {

    func start(sessionToken: String) {
        let session = IncdOnboardingSessionConfiguration(token: sessionToken)

        let flowConfig = IncdOnboardingFlowConfiguration()
        flowConfig.addGeolocation(isSkippable: false)

        IncdOnboardingManager.shared.startOnboarding(
            sessionConfig: session,
            flowConfig: flowConfig,
            delegate: self
        )
    }

    // MARK: - IncdOnboardingDelegate

    func onGeolocationCompleted(_ result: GeolocationResult) {
        // Location step finished. Inspect the result.
        if let coordinates = result.coordinates {
            let latitude = coordinates.latitude
            let longitude = coordinates.longitude
        }
    }

    func onSuccess() { /* flow completed */ }
    func onError(_ error: IncdFlowError) { /* handle error */ }
}
```

## Configuration Options

Configure the module with `addGeolocation()`.

| Option        | Type   | Description                                                                                                                                                                                                                                                                                                                                                                                                       |
| ------------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `isSkippable` | `Bool` | Controls the outcome when the user exits without a location fix, whether by denying permission and skipping, or by exhausting retries on the unavailable screen. When `true`, the user can skip and the flow continues, surfacing `GeolocationError.locationUnavailable` in the result. When `false`, a module that exhausts retries ends the flow with `IncdFlowError.locationUnavailable`. Defaults to `false`. |

## Result

Geolocation delivers a `GeolocationResult` to the `onGeolocationCompleted(_:)` callback on your `IncdOnboardingDelegate`:

```swift
func onGeolocationCompleted(_ result: GeolocationResult)
```

`GeolocationResult` fields:

- `addressFields: OCRDataAddress?`: The captured location broken down into address fields; `nil` when unavailable.
- `coordinates: (latitude: Double, longitude: Double)?`: The latitude and longitude of the captured location, in degrees; `nil` when no fix was obtained.
- `error: GeolocationError?`: The error that occurred while capturing the location, if any; otherwise, `nil`.

## Errors

iOS carries the failure path inline on the same `GeolocationResult`, through its `error` property, rather than through a separate failure callback. `GeolocationError` has the following cases:

- `error(_ error: IncdError)`: A wrapped underlying error.
- `permissionsDenied`: The user denied location permission.
- `noLocationExtracted`: No location could be extracted.
- `noNetworkError`: The location could not be resolved because of a network problem.
- `locationUnavailable`: No location fix was obtained.
  - A non-skippable module that exhausts retries reports `IncdFlowError.locationUnavailable`.
  - A skippable module that is skipped surfaces `GeolocationError.locationUnavailable` in the result.

## Headless

Run the module directly, outside a configured flow, with the manager's headless API, `geolocation(interviewId:completion:)`. The `interviewId` parameter is optional; if omitted, the module falls back to the `interviewId` of the currently active session. The result is delivered through the completion handler as a `GeolocationResult`:

```swift
IncdOnboardingManager.shared.geolocation { result in
    // GeolocationResult
}
```

Requires an active session.

<br />
