> ## 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 Feature Flags

> Toggle features on and off without app updates

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

The feature flags module lets you enable or disable features remotely from the AppDNA Console. Flags are evaluated locally from cached config -- no network call, no latency.

## Check a Flag

```swift theme={null}
if AppDNA.features.isEnabled("dark_mode") {
    enableDarkMode()
}
```

`isEnabled()` returns `false` by default if the flag does not exist or config has not loaded.

## Module Access

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

### Module Methods

| Method       | Signature                            | Description                        |
| ------------ | ------------------------------------ | ---------------------------------- |
| `isEnabled`  | `isEnabled(_ flag: String) -> Bool`  | Check if a feature flag is enabled |
| `getVariant` | `getVariant(_ flag: String) -> Any?` | Get the variant value for a flag   |

## Using Flags with Experiments

Feature flags and experiments work together. A common pattern is to gate a feature behind a flag, then run an experiment to test its impact:

```swift theme={null}
// Flag controls whether the feature is available at all
if AppDNA.features.isEnabled("new_workout_ui") {
    // Experiment controls which variant of the feature to show
    let variant = AppDNA.experiments.getVariant("workout_ui_test")

    switch variant {
    case "compact":
        showCompactWorkoutUI()
    case "detailed":
        showDetailedWorkoutUI()
    default:
        showDefaultWorkoutUI()
    }
} else {
    showLegacyWorkoutUI()
}
```

## Listen for Flag Changes

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

```swift theme={null}
AppDNA.features.onChanged {
    // Feature flags were updated
    let isPremium = AppDNA.features.isEnabled("premium_features")
}
```

## Full Example

```swift theme={null}
import AppDNASDK

class FeatureGate {
    func checkAccess(feature: String, onLocked: () -> Void, onUnlocked: () -> Void) {
        if AppDNA.features.isEnabled(feature) {
            onUnlocked()
        } else {
            onLocked()
        }
    }
}

// Usage
let gate = FeatureGate()

gate.checkAccess(feature: "ai_suggestions",
    onLocked: {
        // Show upgrade prompt or paywall
        AppDNA.paywall.present("premium_paywall", from: self, context: PaywallContext(placement: "feature_gate"))
    },
    onUnlocked: {
        showAISuggestions()
    }
)
```

<Note>
  Feature flags are managed in the Console under **Settings > Feature Flags**. Toggle a flag on or off and it takes effect on the next SDK config refresh (within the TTL window, default 1 hour).
</Note>
