{"id":50478677,"url":"https://github.com/featurevisor/featurevisor-swift2","last_synced_at":"2026-06-01T15:31:55.855Z","repository":{"id":341918697,"uuid":"1172028844","full_name":"featurevisor/featurevisor-swift2","owner":"featurevisor","description":"Swift SDK for Featurevisor v2 and above","archived":false,"fork":false,"pushed_at":"2026-03-03T21:56:38.000Z","size":50,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-03-04T01:41:57.480Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/featurevisor.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-03T21:47:57.000Z","updated_at":"2026-03-03T22:38:09.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/featurevisor/featurevisor-swift2","commit_stats":null,"previous_names":["featurevisor/featurevisor-swift2"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/featurevisor/featurevisor-swift2","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/featurevisor%2Ffeaturevisor-swift2","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/featurevisor%2Ffeaturevisor-swift2/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/featurevisor%2Ffeaturevisor-swift2/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/featurevisor%2Ffeaturevisor-swift2/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/featurevisor","download_url":"https://codeload.github.com/featurevisor/featurevisor-swift2/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/featurevisor%2Ffeaturevisor-swift2/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33782314,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-01T02:00:06.963Z","response_time":115,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-01T15:31:55.171Z","updated_at":"2026-06-01T15:31:55.849Z","avatar_url":"https://github.com/featurevisor.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Featurevisor Swift SDK \u003c!-- omit in toc --\u003e\n\nThis is a port of Featurevisor [Javascript SDK](https://featurevisor.com/docs/sdks/javascript/) v2.x to Swift, providing a way to evaluate feature flags, variations, and variables in your Swift applications.\n\nThis SDK is compatible with [Featurevisor](https://featurevisor.com/) v2.0 projects and above.\n\n## Table of contents \u003c!-- omit in toc --\u003e\n\n- [Installation](#installation)\n- [Initialization](#initialization)\n- [Evaluation types](#evaluation-types)\n- [Context](#context)\n  - [Setting initial context](#setting-initial-context)\n  - [Setting after initialization](#setting-after-initialization)\n  - [Replacing existing context](#replacing-existing-context)\n  - [Manually passing context](#manually-passing-context)\n- [Check if enabled](#check-if-enabled)\n- [Getting variation](#getting-variation)\n- [Getting variables](#getting-variables)\n  - [Type specific methods](#type-specific-methods)\n- [Getting all evaluations](#getting-all-evaluations)\n- [Sticky](#sticky)\n  - [Initialize with sticky](#initialize-with-sticky)\n  - [Set sticky afterwards](#set-sticky-afterwards)\n- [Setting datafile](#setting-datafile)\n  - [Updating datafile](#updating-datafile)\n  - [Interval-based update](#interval-based-update)\n- [Logging](#logging)\n  - [Levels](#levels)\n  - [Customizing levels](#customizing-levels)\n  - [Handler](#handler)\n- [Events](#events)\n  - [`datafile_set`](#datafile_set)\n  - [`context_set`](#context_set)\n  - [`sticky_set`](#sticky_set)\n- [Evaluation details](#evaluation-details)\n- [Hooks](#hooks)\n  - [Defining a hook](#defining-a-hook)\n  - [Registering hooks](#registering-hooks)\n- [Child instance](#child-instance)\n- [Close](#close)\n- [CLI usage](#cli-usage)\n  - [Test](#test)\n  - [Benchmark](#benchmark)\n  - [Assess distribution](#assess-distribution)\n- [Development of this package](#development-of-this-package)\n  - [Running tests](#running-tests)\n- [License](#license)\n\n\u003c!-- FEATUREVISOR_DOCS_BEGIN --\u003e\n\n## Installation\n\nIn your Swift application, add this package using Swift Package Manager:\n\n```swift\n.package(url: \"https://github.com/featurevisor/featurevisor-swift2.git\", from: \"0.1.0\")\n```\n\nThen add the product dependency:\n\n```swift\n.product(name: \"Featurevisor\", package: \"featurevisor-swift2\")\n```\n\n## Initialization\n\nThe SDK can be initialized by passing [datafile](https://featurevisor.com/docs/building-datafiles/) content directly:\n\n```swift\nimport Foundation\nimport Featurevisor\n\nlet datafileURL = URL(string: \"https://cdn.yoursite.com/datafile.json\")!\nlet data = try Data(contentsOf: datafileURL)\nlet datafileContent = try DatafileContent.fromData(data)\n\nlet f = createInstance(\n    InstanceOptions(\n        datafile: datafileContent\n    )\n)\n```\n\n## Evaluation types\n\nWe can evaluate 3 types of values against a particular [feature](https://featurevisor.com/docs/features/):\n\n- [**Flag**](#check-if-enabled) (`Bool`): whether the feature is enabled or not\n- [**Variation**](#getting-variation) (`String`): the variation of the feature (if any)\n- [**Variables**](#getting-variables): variable values of the feature (if any)\n\nThese evaluations are run against the provided context.\n\n## Context\n\nContexts are [attribute](https://featurevisor.com/docs/attributes) values that we pass to SDK for evaluating [features](https://featurevisor.com/docs/features) against.\n\nThink of the conditions that you define in your [segments](https://featurevisor.com/docs/segments/), which are used in your feature's [rules](https://featurevisor.com/docs/features/#rules).\n\nThey are plain dictionaries:\n\n```swift\nlet context: Context = [\n    \"userId\": .string(\"123\"),\n    \"country\": .string(\"nl\"),\n]\n```\n\n### Setting initial context\n\nYou can set context at the time of initialization:\n\n```swift\nlet f = createInstance(\n    InstanceOptions(\n        context: [\n            \"deviceId\": .string(\"123\"),\n            \"country\": .string(\"nl\"),\n        ]\n    )\n)\n```\n\n### Setting after initialization\n\nYou can also set more context after the SDK has been initialized:\n\n```swift\nf.setContext([\n    \"userId\": .string(\"234\"),\n])\n```\n\nThis will merge the new context with the existing one (if already set).\n\n### Replacing existing context\n\nIf you wish to fully replace the existing context, you can pass `true` in second argument:\n\n```swift\nf.setContext(\n    [\n        \"deviceId\": .string(\"123\"),\n        \"userId\": .string(\"234\"),\n        \"country\": .string(\"nl\"),\n        \"browser\": .string(\"chrome\"),\n    ],\n    replace: true\n)\n```\n\n### Manually passing context\n\nYou can optionally pass additional context manually for each and every evaluation separately, without needing to set it to the SDK instance affecting all evaluations:\n\n```swift\nlet context: Context = [\n    \"userId\": .string(\"123\"),\n    \"country\": .string(\"nl\"),\n]\n\nlet isEnabled = f.isEnabled(\"my_feature\", context)\nlet variation = f.getVariation(\"my_feature\", context)\nlet variableValue = f.getVariable(\"my_feature\", \"my_variable\", context)\n```\n\nWhen manually passing context, it will merge with existing context set to the SDK instance before evaluating the specific value.\n\n## Check if enabled\n\nOnce the SDK is initialized, you can check if a feature is enabled or not:\n\n```swift\nlet featureKey = \"my_feature\"\n\nlet isEnabled = f.isEnabled(featureKey)\n\nif isEnabled {\n    // do something\n}\n```\n\nYou can also pass additional context per evaluation:\n\n```swift\nlet isEnabled = f.isEnabled(featureKey, [\n    // ...additional context\n])\n```\n\n## Getting variation\n\nIf your feature has any [variations](https://featurevisor.com/docs/features/#variations) defined, you can evaluate them as follows:\n\n```swift\nlet featureKey = \"my_feature\"\n\nlet variation = f.getVariation(featureKey)\n\nif variation == \"treatment\" {\n    // do something for treatment variation\n} else {\n    // handle default/control variation\n}\n```\n\nAdditional context per evaluation can also be passed:\n\n```swift\nlet variation = f.getVariation(featureKey, [\n    // ...additional context\n])\n```\n\n## Getting variables\n\nYour features may also include [variables](https://featurevisor.com/docs/features/#variables), which can be evaluated as follows:\n\n```swift\nlet variableKey = \"bgColor\"\nlet bgColorValue = f.getVariable(\"my_feature\", variableKey)\n```\n\nAdditional context per evaluation can also be passed:\n\n```swift\nlet bgColorValue = f.getVariable(\"my_feature\", variableKey, [\n    // ...additional context\n])\n```\n\n### Type specific methods\n\nNext to generic `getVariable()` methods, there are also type specific methods available for convenience:\n\n```swift\nf.getVariableBoolean(featureKey, variableKey, context)\nf.getVariableString(featureKey, variableKey, context)\nf.getVariableInteger(featureKey, variableKey, context)\nf.getVariableDouble(featureKey, variableKey, context)\nf.getVariableArray(featureKey, variableKey, context)\nf.getVariableObject(featureKey, variableKey, context)\nf.getVariableJSON(featureKey, variableKey, context)\n```\n\n## Getting all evaluations\n\nYou can get evaluations of all features available in the SDK instance:\n\n```swift\nlet allEvaluations = f.getAllEvaluations([:])\nprint(allEvaluations)\n```\n\nThis is handy especially when you want to pass all evaluations from a backend application to the frontend.\n\n## Sticky\n\nFor the lifecycle of the SDK instance in your application, you can set some features with sticky values, meaning that they will not be evaluated against the fetched [datafile](https://featurevisor.com/docs/building-datafiles/):\n\n### Initialize with sticky\n\n```swift\nlet f = createInstance(\n    InstanceOptions(\n        sticky: [\n            \"myFeatureKey\": EvaluatedFeature(\n                enabled: true,\n                variation: \"treatment\",\n                variables: [\"myVariableKey\": .string(\"myVariableValue\")]\n            ),\n            \"anotherFeatureKey\": EvaluatedFeature(enabled: false),\n        ]\n    )\n)\n```\n\n### Set sticky afterwards\n\n```swift\nf.setSticky([\n    \"myFeatureKey\": EvaluatedFeature(\n        enabled: true,\n        variation: \"treatment\",\n        variables: [\"myVariableKey\": .string(\"myVariableValue\")]\n    ),\n    \"anotherFeatureKey\": EvaluatedFeature(enabled: false),\n], replace: true)\n```\n\n## Setting datafile\n\nYou may also initialize the SDK without passing `datafile`, and set it later on:\n\n```swift\nf.setDatafile(datafileContent)\n```\n\nYou can also set using raw JSON string:\n\n```swift\nf.setDatafile(json: jsonString)\n```\n\n### Updating datafile\n\nYou can set the datafile as many times as you want in your application, which will result in emitting a [`datafile_set`](#datafile_set) event that you can listen and react to accordingly.\n\n### Interval-based update\n\n```swift\nimport Foundation\n\nlet interval: TimeInterval = 5 * 60\nTimer.scheduledTimer(withTimeInterval: interval, repeats: true) { _ in\n    if let data = try? Data(contentsOf: datafileURL),\n       let datafile = try? DatafileContent.fromData(data) {\n        f.setDatafile(datafile)\n    }\n}\n```\n\n## Logging\n\nBy default, Featurevisor SDK logs from `info` level and above.\n\n### Levels\n\nThese are available log levels:\n\n- `debug`\n- `info`\n- `warn`\n- `error`\n- `fatal`\n\n### Customizing levels\n\nYou can set log level at initialization:\n\n```swift\nlet f = createInstance(\n    InstanceOptions(\n        logLevel: .debug\n    )\n)\n```\n\nOr set it afterwards:\n\n```swift\nf.setLogLevel(.debug)\n```\n\n### Handler\n\nIf you want to fully control log output, pass a custom logger:\n\n```swift\nlet logger = createLogger(level: .debug) { level, message, details in\n    print(\"[\\(level)] \\(message) \\(details)\")\n}\n\nlet f = createInstance(\n    InstanceOptions(\n        datafile: datafileContent,\n        logger: logger\n    )\n)\n```\n\n## Events\n\nFeaturevisor SDK implements a simple event emitter that allows you to listen to runtime events.\n\n### `datafile_set`\n\n```swift\nlet unsubscribe = f.on(.datafileSet) { payload in\n    print(payload.params)\n}\n\nunsubscribe()\n```\n\n### `context_set`\n\n```swift\nlet unsubscribe = f.on(.contextSet) { _ in\n    // handle context updates\n}\n\nunsubscribe()\n```\n\n### `sticky_set`\n\n```swift\nlet unsubscribe = f.on(.stickySet) { _ in\n    // handle sticky updates\n}\n\nunsubscribe()\n```\n\n## Evaluation details\n\nIf you need evaluation metadata, use:\n\n```swift\nlet flagDetails = f.evaluateFlag(\"my_feature\")\nlet variationDetails = f.evaluateVariation(\"my_feature\")\nlet variableDetails = f.evaluateVariable(\"my_feature\", \"my_variable\")\n```\n\n## Hooks\n\nHooks allow you to intercept evaluation inputs and outputs.\n\n### Defining a hook\n\n```swift\nlet hook = Hook(\n    name: \"my-hook\",\n    before: { input in\n        input\n    },\n    after: { evaluation, _ in\n        evaluation\n    }\n)\n```\n\n### Registering hooks\n\n```swift\nlet f = createInstance(\n    InstanceOptions(\n        hooks: [hook]\n    )\n)\n\nlet removeHook = f.addHook(hook)\nremoveHook()\n```\n\n## Child instance\n\nYou can spawn child instances with inherited context:\n\n```swift\nlet child = f.spawn([\n    \"userId\": .string(\"123\"),\n])\n\nlet enabled = child.isEnabled(\"my_feature\")\n```\n\n## Close\n\nTo clear listeners and close resources:\n\n```swift\nf.close()\n```\n\n## CLI usage\n\nThe package also ships an executable named `featurevisor`.\n\n### Test\n\n```bash\nswift run featurevisor test \\\n  --projectDirectoryPath=/path/to/featurevisor-project\n```\n\nWith scoped and tagged datafiles:\n\n```bash\nswift run featurevisor test \\\n  --projectDirectoryPath=/path/to/featurevisor-project \\\n  --with-scopes \\\n  --with-tags\n```\n\n### Benchmark\n\n```bash\nswift run featurevisor benchmark \\\n  --projectDirectoryPath=/path/to/featurevisor-project \\\n  --environment=production \\\n  --feature=my_feature \\\n  --context='{\"userId\":\"123\"}' \\\n  --n=1000\n```\n\n### Assess distribution\n\n```bash\nswift run featurevisor assess-distribution \\\n  --projectDirectoryPath=/path/to/featurevisor-project \\\n  --environment=production \\\n  --feature=my_feature \\\n  --populateUuid=userId \\\n  --n=1000\n```\n\n\u003c!-- FEATUREVISOR_DOCS_END --\u003e\n\n## Development of this package\n\n### Running tests\n\n```bash\nswift test\n```\n\n## License\n\nMIT © [Fahad Heylaal](https://fahad19.com)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffeaturevisor%2Ffeaturevisor-swift2","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffeaturevisor%2Ffeaturevisor-swift2","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffeaturevisor%2Ffeaturevisor-swift2/lists"}