# Predictive Document Verification (DocV) iOS SDKs

iOS SDKs that capture documents or images require access to the device camera. On iOS, camera access is fully controlled by the operating system and gated by explicit user consent.

If camera access isn’t granted, document capture cannot proceed.

## How iOS camera permissions work

iOS shows the system camera permission prompt **once per app**:

> “ _App Name_ would like to access the camera”

If the user taps **Don’t Allow**, iOS will not show the prompt again automatically. The SDK cannot re-request permission on your behalf. Only the user can re-enable camera access from **Settings**.

Your app must detect this state and guide the user accordingly.

## Camera authorization states

Camera access can be in one of four states:

| State          | Meaning                                            | What you can do                               |
|----------------|---------------------------------------------------|------------------------------------------------|
| `notDetermined`| User has not been prompted yet                     | You may request access (system prompt appears) |
| `authorized`   | User granted access                                | Camera capture can proceed                     |
| `denied`      | User denied access                                 | User must enable access in Settings            |
| `restricted`   | Access blocked by system policy (MDM, parental controls) | Cannot be resolved programmatically            |

## Required configuration

Before using any DocV SDK feature that accesses the camera, your app **must** declare a camera usage description in `Info.plist`.

XML

```xml
<key>NSCameraUsageDescription</key>
<string>Camera access is required to capture documents for identity verification.</string>
```

If this key is missing:

- iOS will terminate the app when camera access is attempted.
- The DocV SDK will not be able to start a capture session.

## Recommended integration patterns

### Option 1 — Handle permission denial after SDK launch

If the DocV SDK returns an error indicating camera access was declined, your app should:

1. Detect the permission-denied error.
2. Explain why camera access is required.
3. Provide a clear path to **Settings**.

**Suggested copy**

- **Title:** Camera access needed
- **Message:** Camera access is required to complete document capture. Enable it in Settings to continue.
- **Action:** Open Settings

### Option 2 — Pre-check permission before launching DocV (recommended)

This approach avoids starting a DocV session when camera access is unavailable.

**Flow**

1. Check the current camera authorization state.
2. If `notDetermined`, request permission (system prompt appears once).
3. If `denied` or `restricted`, show your own UI and link to Settings.
4. Launch DocV **only** after access is `authorized`.

## Example implementation

This example pre-checks and requests camera permission before launching a DocV session.

Swift

```swift
import UIKit
import AVFoundation
import SocureDocV

class ViewController: UIViewController {

@IBOutlet weak var lblStatus: UILabel!

override func viewDidLoad() {
        super.viewDidLoad()
    }

// MARK: - UI Helpers
    func updateStatus(_ status: String) {
        DispatchQueue.main.async { [weak self] in
            self?.lblStatus.text = status
        }
    }

// MARK: - Camera Permission Handling
    private func checkAndRequestCameraPermission(
        completion: @escaping (Bool) -> Void
    ) {
        let status = AVCaptureDevice.authorizationStatus(for: .video)

switch status {
        case .notDetermined:
            // First time: show the system prompt
            AVCaptureDevice.requestAccess(for: .video) { granted in
                DispatchQueue.main.async {
                    if granted {
                        completion(true)
                    } else {
                        self.showCameraDeniedAlert(firstTime: true)
                        completion(false)
                    }
                }
            }

case .authorized:
            // Already allowed → good to go
            completion(true)

case .denied, .restricted:
            // User denied previously, or device restrictions apply
            showCameraDeniedAlert(firstTime: false)
            completion(false)

@unknown default:
            completion(false)
        }
    }

private func showCameraDeniedAlert(firstTime: Bool) {
        let title = "Camera Access Needed"
        let message: String

if firstTime {
            message = "Camera access is required to complete the document capture. Please enable it in Settings if you’d like to proceed."
        } else {
            message = "Camera access has been disabled for this app. Please go to Settings → Privacy → Camera and enable access to continue."
        }

let alert = UIAlertController(
            title: title,
            message: message,
            preferredStyle: .alert
        )

// Open Settings button
        let settingsAction = UIAlertAction(
            title: "Open Settings",
            style: .default
        ) { _ in
            guard let settingsURL = URL(
                string: UIApplication.openSettingsURLString
            ) else { return }

if UIApplication.shared.canOpenURL(settingsURL) {
                UIApplication.shared.open(
                    settingsURL,
                    options: [:],
                    completionHandler: nil
                )
            }
        }

let cancelAction = UIAlertAction(
            title: "Cancel",
            style: .cancel,
            handler: nil
        )

alert.addAction(settingsAction)
        alert.addAction(cancelAction)
        present(alert, animated: true, completion: nil)
    }

// MARK: - DocV Launch
    private func startDocVFlow() {
        let options = SocureDocVOptions(
            publicKey: "YOUR_PUBLIC_KEY",
            docvTransactionToken: "YOUR_TRANSACTION_TOKEN",
            presentingViewController: self,
            useSocureGov: false
        )

SocureDocVSDK.launch(options) { [weak self] result in
            switch result {
            case .success(let successResult):
                self?.updateStatus("Upload Success: \(successResult)")
                print(successResult)

case .failure(let failureResult):
                self?.updateStatus("Upload Failure: \(failureResult.error)")
                print(failureResult)
            }
        }
    }

// MARK: - IBActions
    @IBAction func startScan(_ sender: Any) {
        // 1) Check / request camera permission
        checkAndRequestCameraPermission { [weak self] granted in
            guard let self = self else { return }

if granted {
                // 2) If granted, start the DocV flow
                self.startDocVFlow()
            } else {
                self.updateStatus("Camera permission not granted")
            }
        }
    }
}
```

## Key points in the example

- **Check authorization state first** using `AVCaptureDevice.authorizationStatus(for: .video)`.
- **Only request permission** when status is `notDetermined`. This is the only state that can trigger the system prompt.
- **Handle `denied` and `restricted`** with app-owned UI and a clear path to Settings.
- **Deep-link to Settings** with `UIApplication.openSettingsURLString`.
- **Launch DocV only when granted** to avoid dead-end sessions.
- **Update UI on the main thread** and avoid retain cycles with `[weak self]`.

## Best practices

- Use a clear, single-purpose message: “Camera access is required to capture your document.”
- Keep the CTA consistent: **Open Settings**.
- If the user returns from Settings without granting permission, **re-check** the status and keep guidance visible.
- Consider tracking denial-related analytics (for example: `permission_denied`, `opened_settings`) to identify drop-off points.
