Evaluate feature flags
Evaluate feature flags and read variant payloads in an iOS app.
getFeatureFlags(_:) evaluates feature flags for the current person, so you can turn features on,
roll them out gradually, or pick a variant without shipping a build. You create flags and set their
rollout in Studio; see Feature flags.
Feature flags are in early access. Ask us on Discord, or email support@voidhash.com on a paid plan, to turn them on for your team.
A build that uses a test key gets each flag's test configuration, which is the same as production's until you change it in Studio. See Environments.
Evaluate flags
Pass the keys you need, or nil to evaluate every flag in the project:
let flags = try await voidhash.getFeatureFlags(["new-onboarding", "pricing-test"])
let newOnboarding = flags.first { $0.key == "new-onboarding" }?.enabled == true
let pricingVariant = flags.first { $0.key == "pricing-test" }?.variantKeyEach SdkFeatureFlagResult has key, enabled, variantKey (the assigned variant, or nil) and
payload. A flag that is off returns enabled: false with no variant. A key without a result,
such as one Voidhash doesn't know, is missing from the list unless it has a
default: treat a missing flag as off.
Don't gate paid access on a flag. Use perks for that.
Read a variant's payload
A variant can carry a JSON payload, such as a headline or a pricing configuration. payload is a
JSONValue, or nil when the variant has none. Validate it before use:
import Voidhash
import VoidhashCore
func trialDays() async -> Int {
let flag = try? await Voidhash.shared?.getFeatureFlags(["pricing-test"]).first
if case .object(let config)? = flag?.payload, case .number(let days)? = config["trialDays"] {
return Int(days)
}
return 7
}Defaults and slow networks
Results are cached on the device per person and kept while Voidhash is unreachable. A fresh result
answers at once; a result older than 5 minutes waits up to 500 milliseconds for a new evaluation.
Only a read with nothing cached waits longer, up to maxWaitMilliseconds (2,000 by default). After
that, each requested key reads as its defaults entry and the evaluation continues in the
background. onUpdate tells you when it arrives:
var options = VoidhashOptions()
options.featureFlags.defaults = ["new-onboarding": false]
options.featureFlags.maxWaitMilliseconds = 2000
options.featureFlags.onUpdate = { keys, flags in
Task { @MainActor in FlagStore.shared.reload() }
}
Voidhash.configure(publishableKey: "vh_pk_...", options: options)onUpdate is called with the evaluated keys (nil for every flag) and results each time a new
evaluation is stored for the current person. It runs on an SDK task, so return quickly and move UI
work to the main actor.
getFeatureFlagsState(_:) returns the same results with isStale, isExpired and reason, so you
can tell a fresh evaluation from a cached or default one.
Identity changes
Results belong to the current distinct ID. After identify, the flags evaluated for the anonymous
person keep answering until the identified person's evaluation replaces them, so features don't
flip to their defaults while Voidhash is unreachable. Identifying can assign a different variant
than the anonymous person had. Signing out, switching users, or a sign-in Voidhash refuses clears
the cached results.
Next steps
Something wrong or missing on this page? Tell us by email or on Discord.