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

# iOS Remote Config

> Read remote configuration values from the AppDNA Console

<Info>
  **Supported on:** iOS SDK `1.0.61+`
</Info>

The remote config module delivers key-value pairs from the AppDNA Console to your app. Values are set in the Console and synced to the SDK automatically. All reads are synchronous from an in-memory cache -- they never block the UI thread or require a network call.

## Get Config Values

Read values using the `get` method. Returns `Any?` -- you cast to the expected type on your side.

```swift theme={null}
let welcome = AppDNA.remoteConfig.get("welcome_message") as? String ?? "Hello!"
let maxRetries = AppDNA.remoteConfig.get("max_retries") as? Int ?? 3
let discount = AppDNA.remoteConfig.get("discount_rate") as? Double ?? 0.1
let promoEnabled = AppDNA.remoteConfig.get("show_promo") as? Bool ?? false
```

To retrieve all config values at once:

```swift theme={null}
let allConfig = AppDNA.remoteConfig.getAll()
// Returns [String: Any] -- all currently cached config key-value pairs
```

## Module Access

```swift theme={null}
let remoteConfig = AppDNA.remoteConfig
```

### Module Methods

| Method      | Signature                                    | Description               |
| ----------- | -------------------------------------------- | ------------------------- |
| `get`       | `get(_ key: String) -> Any?`                 | Get a config value        |
| `getAll`    | `getAll() -> [String: Any]`                  | Get all config values     |
| `refresh`   | `refresh()`                                  | Force refresh from server |
| `onChanged` | `onChanged(_ handler: @escaping () -> Void)` | Register change callback  |

## When Config Refreshes

The SDK refreshes remote config automatically:

* **On app launch** -- if the cached config has expired (default TTL: 1 hour)
* **On return from background** -- same TTL check
* **Background fetch** -- the SDK checks for updates periodically

You can also force a refresh manually with `AppDNA.remoteConfig.refresh()`. If the fetch fails (no connectivity, timeout), the SDK continues using the cached values. On first launch with no connectivity, bundled config defaults are used.

<Info>
  The config TTL is configurable via `AppDNAOptions(configTTL: 7200)` (in seconds). The default is 3600 seconds (1 hour).
</Info>

## Listen for Config Changes

Register a closure to be notified when remote config values change after a refresh:

```swift theme={null}
AppDNA.remoteConfig.onChanged {
    // Config values were updated -- re-read any values you need
    let newValue = AppDNA.remoteConfig.get("feature_limit")
}
```

## Full Example

```swift theme={null}
import AppDNASDK

class HomeViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()

        AppDNA.remoteConfig.onChanged { [weak self] in
            // Refresh UI when config changes in the background
            DispatchQueue.main.async {
                self?.configureUI()
            }
        }

        configureUI()
    }

    func configureUI() {
        // Read values -- always synchronous, always available
        let title = AppDNA.remoteConfig.get("home_title") as? String ?? "Welcome"
        let showBanner = AppDNA.remoteConfig.get("show_promo_banner") as? Bool ?? false
        let bannerText = AppDNA.remoteConfig.get("promo_banner_text") as? String ?? ""

        titleLabel.text = title

        if showBanner {
            promoBanner.text = bannerText
            promoBanner.isHidden = false
        }
    }
}
```

<Note>
  Remote config values are managed in the Console under **Settings > Remote Config**. Changes take effect on the next SDK config refresh (within the TTL window).
</Note>
