Skip to content
Everframe Docs
Documentation

Install

A binary Swift package. Add it, start it, and wire the reporter to your own button. On tvOS it captures crashes, errors and replays; there is no on-device reporter.

Updated

Swift Package Manager

// Package.swift
.package(url: "https://github.com/scriptx-com/everframe", from: "1.2.1")

// Then, on your app target:
.product(name: "Everframe", package: "everframe"),
.product(name: "EverframeReporterUI", package: "everframe"),

from: resolves the newest release from 1.2.1, the current release, up to the next major version, so later 1.x releases arrive without editing this line.

Or in Xcode: File → Add Package Dependencies, paste the URL, and add both products to your app target. Everframe is the SDK; EverframeReporterUI is the reporter modal. Without the second, report.open() has nothing to open.

CocoaPods

pod 'Everframe'             # the SDK (the Core subspec)
pod 'Everframe/ReporterUI'  # the reporter modal

Start it

Once, as early as you can. The same code works in an iOS and a tvOS target.

In a SwiftUI app, put it in your App initialiser:

import SwiftUI
import EverframeKit
import EverframeReporterUI

@main
struct MyApp: App {
    init() {
        EFReporterPresenter.installResolver()
        do {
            try Everframe.shared.start(config: EverframeConfig(sdkKey: "evf_live_…"))
        } catch {
            print("Everframe did not start: \(error)")
        }
    }

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

With a UIKit app delegate, put it in application(_:didFinishLaunchingWithOptions:):

import UIKit
import EverframeKit
import EverframeReporterUI

@main
final class AppDelegate: UIResponder, UIApplicationDelegate {
    func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        EFReporterPresenter.installResolver()
        do {
            try Everframe.shared.start(config: EverframeConfig(sdkKey: "evf_live_…"))
        } catch {
            print("Everframe did not start: \(error)")
        }
        return true
    }
}

The module is EverframeKit, even though the package product is Everframe.

EverframeConfig(sdkKey:) takes your SDK key (evf_live_…), the key the app’s Setup tab in the dashboard fills in. It is not the App ID (a UUID); only symbol uploads take that. See the table below. start throws EverframeConfigError.missingSdkKey when the key is blank, does not start with evf_live_, or is the wrong length. Catch it as above: an initialiser cannot throw, and a bad key should not stop your app from launching. Check the log during development, because an app with a bad key never reports.

installResolver() wires the reporter to report.open(). Call it once at launch; without it open() throws on iOS. There is no on-device reporter on tvOS, where installResolver() does nothing, so the same launch code builds for both.

Native crash capture is on by default and needs nothing beyond start(). See Crash reporting for what is captured.

Which value goes where

The dashboard shows two values for each app, and they are not interchangeable:

Where it goesValueWhere to find it
EverframeConfig(sdkKey:) in your appThe SDK key, evf_live_…. Publishable; it can only submit reports.The app’s Setup tab fills it in; manage keys on SDK keys.
Symbol upload: --app-id in the Xcode phase, or the EVERFRAME_APP_ID build settingThe App ID, a UUID.App ID on the app’s Setup tab.
EVERFRAME_API_TOKEN in CIAn API token with the artifacts:write scope. Never put it in the app.Settings → API tokens.

A project with an iPhone target and an Apple TV target that report to two Everframe apps has two of each: give each target its own SDK key (for example through a per-target Info.plist value) and its own App ID for symbol upload, as described in Apple dSYMs.

Open the reporter

Opening is on the report API, and it is async throws — it returns when the user submits or cancels:

Task {
    let result = try await Everframe.shared.report.open()
}

result is .submitted, .queued (stored offline, sent on a later launch) or .cancelled. Wire it to your own button, a debug menu, or a gesture you own — the SDK installs no trigger of its own.

On tvOS there is no on-screen reporter: installResolver() does nothing there and open() throws. Instead, a linked test Apple TV files a quick capture when you hold Play/Pause.

Requirements

iOS / iPadOS15+
tvOS15+
SwiftPackage manifest is swift-tools-version: 5.10
DistributionBinary framework — the source repo stays private

Verify it

File a report and check the delivery log in the dashboard. If nothing arrives, check captureGate, which reports whether capture is armed at all — start() opens it, kill() closes it:

print(Everframe.shared.captureGate)   // Bool
print(Everframe.shared.currentConfig) // EverframeConfig?

The usual causes are a wrong key in EverframeConfig(sdkKey:) (the App ID UUID instead of the evf_live_… SDK key), and calling start from a code path that does not run on every launch.

Next