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 goes | Value | Where to find it |
|---|---|---|
EverframeConfig(sdkKey:) in your app | The 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 setting | The App ID, a UUID. | App ID on the app’s Setup tab. |
EVERFRAME_API_TOKEN in CI | An 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 / iPadOS | 15+ |
| tvOS | 15+ |
| Swift | Package manifest is swift-tools-version: 5.10 |
| Distribution | Binary 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
- Configuration — every option
- Crash reporting — what is captured, and when it is sent
- Apple dSYMs — readable native crash frames
- Screen tracking — UIKit is automatic, SwiftUI is not
- Sensitive content — mask before capture