VoidhashDocs
DevelopersHelp centerGuidesAPI reference
Dashboard
Get started
Introduction
Quickstart
How Voidhash works
Glossary
Versions and releases
Concepts
Teams, projects and environments
API keys
Products and perks
Offers
Subscription lifecycle
People and identity
Groups
Events
Features
Paywalls in your app
Feature flags and A/B tests
Paywall components
Push notifications
Ad attribution in your app
Client SDKs
React Native
Swift
Kotlin
Web
Your backend
Node.js
PHP
Go
Rust
Other languages
Payment sources
Forward store notifications
Developer tools
CLI
MCP server
Query analytics with VoidQL
Swift SDK
Swift quickstart
Display a paywall
Make and restore purchases
Check access
Identify users
Evaluate feature flags
Capture analytics
Groups
Track screens
Development mode
Swift SDK reference
Errors
Diagnostic codes
Troubleshooting

Swift SDK

Install the Voidhash iOS SDK and create its client.

The Swift SDK adds paywalls, purchases, access checks, feature flags and analytics to native iOS apps built on StoreKit 2. To add it to an app for the first time, follow the Swift quickstart. Options and methods are in the Swift SDK reference.

Requirements

  • iOS 15 or later. Paywalls need UIKit.
  • A Swift 6 toolchain. The sources also build in the Swift 5.9 language mode.
  • StoreKit 2.

The sources also build for visionOS and for app extensions, such as widgets.

Install

The Swift SDK installs with Swift Package Manager from the main branch of the Voidhash repository. In Xcode, choose File → Add Package Dependencies…, enter https://github.com/voidhashcom/voidhash, set the dependency rule to the main branch, and add Voidhash (and VoidhashCore when you need it) to your app target. In a Package.swift:

Package.swift
dependencies: [
    .package(url: "https://github.com/voidhashcom/voidhash", branch: "main")
],
targets: [
    .target(
        name: "App",
        dependencies: [
            .product(name: "Voidhash", package: "voidhash"),
            .product(name: "VoidhashCore", package: "voidhash"),
        ]
    )
]

To pin a build, depend on a commit with revision: "<commit>" instead of branch: "main".

Alpha

The SDK is an alpha release and has no tagged versions yet. Pin a commit and update regularly. See Versions and releases.

The SDK has three library products:

ProductWhat it contains
VoidhashThe client you integrate against: Voidhash.configure(…) returns a VoidhashClient.
VoidhashCoreThe shared native core. It defines the model and error types the SDK returns, such as SdkPerson, JSONValue and VoidhashStoreError. Add it and import VoidhashCore when your code names one of them.
VoidhashUIThe native paywall renderer. Needed only to present paywalls.
Paywalls need a source checkout

The repository URL package doesn't include VoidhashUI, whose engine ships as a binary you build from source. To present paywalls, add the SDK from a local checkout instead, as Display a paywall describes.

CocoaPods

The pods aren't on the CocoaPods trunk. Install their sources, the @voidhash/ios package, from the Voidhash package registry:

npm install @voidhash/ios@https://pkg.voidha.sh/@voidhash/ios/branch:main

Then point both pods at it. Declare both: CocoaPods can't find a local VoidhashCore through the Voidhash dependency alone.

Podfile
pod "VoidhashCore", :path => "../node_modules/@voidhash/ios"
pod "Voidhash", :path => "../node_modules/@voidhash/ios"

To pin a build, install from https://pkg.voidha.sh/@voidhash/ios/<hash>, using the short commit hash at the end of the installed version, such as 83f7412 in 0.0.1-alpha.1-g83f7412. Registry builds are kept for three weeks.

Create the client

Configure one client while the app launches and keep it for the app's lifetime. In a SwiftUI app, do it in the App initializer; in a UIKit app, in application(_:didFinishLaunchingWithOptions:).

MyApp.swift
import SwiftUI
import Voidhash

@main
struct MyApp: App {
    init() {
        Voidhash.configure(publishableKey: "vh_pk_...")
    }

    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

Release builds, including TestFlight and App Review builds, use the production key. Debug builds in development mode use the test key. See API keys.

configure returns the client. Everywhere else, reach it through Voidhash.shared. The examples in these docs call it voidhash.

guard let voidhash = Voidhash.shared else { return }

Don't configure the client in a let at file scope. Swift creates such a global the first time code reads it, so the SDK wouldn't observe transactions or record the launch until then.

Initialization runs in the background: it connects to StoreKit, loads the project's configuration and syncs transactions that happened while the app was away. The first call that needs it waits for it. To wait explicitly, for example behind a loading screen, call try await voidhash.waitForInitialization(). It never fails because Voidhash is unreachable.

VoidhashClient(publishableKey:options:) creates a client without starting it; call start() or waitForInitialization() on it. Prefer Voidhash.configure, which does both and sets shared. To pass options, see Client options.

Privacy manifest

VoidhashCore ships a privacy manifest that Xcode adds to your app's privacy report. It declares no tracking, the UserDefaults API (reason CA92.1) and the system boot time API (reason 35F9.1), and lists the data the SDK sends, all linked to the person and none used for tracking:

Data typeSourcePurpose
User ID, device IDThe distinct IDApp functionality, analytics
Email address, nameWhat you pass to identifyApp functionality
Purchase historyStore transactionsApp functionality, analytics
Product interactionEvents, screens, lifecycle eventsAnalytics
Advertising dataThe Apple Ads campaign behind the installAnalytics
Crash dataThat the app crashed, and in which version; no crash logsAnalytics
Coarse locationCity-level location derived from the request addressAnalytics

The last four are collected only while analytics consent is granted. Declare anything else you send, such as attributes or event properties that hold personal data, in your app's own privacy details.

Next steps

  • Swift quickstart
  • Swift SDK reference
  • Display a paywall
  • Troubleshooting

Something wrong or missing on this page? Tell us by email or on Discord.

PreviousTroubleshootingNextSwift quickstart

On this page

RequirementsInstallCocoaPodsCreate the clientPrivacy manifestNext steps