iOS Quick Start
Integrate Traceway into your native iOS application with the traceway-ios (opens in a new tab) Swift package. Pure Swift, zero third-party dependencies. It captures errors and crashes only (no metrics, no transactions, no session replay) and speaks the same /api/report wire format as the other SDKs, so a single Traceway backend handles iOS alongside everything else.
Requirements
- iOS 13.0+
- Swift 5.9+ / Xcode 15+
Installation
Install with Swift Package Manager. In Xcode, choose File > Add Package Dependencies and enter the repository URL:
https://github.com/tracewayapp/traceway-ios.gitOr add it directly to your Package.swift:
dependencies: [
.package(url: "https://github.com/tracewayapp/traceway-ios.git", from: "0.1.0"),
],Then add the Traceway product to your target's dependencies. The package identity is traceway-ios and the library product is Traceway, so the two names differ and SwiftPM needs the explicit .product(name:package:) form:
.target(
name: "MyApp",
dependencies: [.product(name: "Traceway", package: "traceway-ios")]
),Setup
Call Traceway.start(connectionString:options:) as early as possible so it is installed before any code that might crash. In SwiftUI, do it from your App.init:
import SwiftUI
import Traceway
@main
struct MyApp: App {
init() {
Traceway.start(
connectionString: "your-token@https://cloud.tracewayapp.com/api/report",
options: TracewayOptions(version: "1.0.0")
)
}
var body: some Scene {
WindowGroup {
ContentView()
}
}
}In UIKit, do it from application(_:didFinishLaunchingWithOptions:):
import UIKit
import Traceway
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
Traceway.start(
connectionString: "your-token@https://cloud.tracewayapp.com/api/report",
options: TracewayOptions(version: "1.0.0")
)
return true
}
}What Gets Captured Automatically
After Traceway.start(...) runs, the following sources are captured with no additional configuration:
- Uncaught NSExceptions: ObjC / UIKit exceptions that escape to the top of the stack.
- Fatal signals: Swift runtime traps such as force-unwrapping a
nil, array out-of-bounds access,fatalError(), and integer overflow, surfacing asSIGTRAP,SIGILL,SIGABRT, orSIGSEGV.
Hard crashes are persisted to disk and uploaded on the next launch, so a crash that takes the process down still reaches your dashboard.
Capture Errors Manually
import Traceway
// Capture any Swift Error
do {
try riskyOperation()
} catch {
Traceway.capture(error)
}
// Capture an NSError
Traceway.capture(error: nsError)
// Capture a message
Traceway.capture(message: "User completed onboarding")
// Force send pending reports (seconds; nil waits indefinitely)
Traceway.flush(timeout: 5)With Options
TracewayOptions accepts the following parameters. Field names mirror the other SDKs so configuration can be ported directly.
| Option | Default | Description |
|---|---|---|
sampleRate | 1.0 | Fraction of exceptions to keep (0.0 to 1.0) |
debug | false | Log SDK activity via NSLog |
version | "" | App version, sent as appVersion |
debounceMs | 1500 | Delay before batching and uploading |
retryDelayMs | 10000 | Delay before retrying a failed upload |
maxPendingExceptions | 5 | In-memory cap; oldest dropped when exceeded |
persistToDisk | true | Persist pending reports so they survive restarts |
maxLocalFiles | 5 | Max persisted report files |
localFileMaxAgeHours | 12 | Delete unsynced files older than this |
Traceway.start(
connectionString: "your-token@https://cloud.tracewayapp.com/api/report",
options: TracewayOptions(
sampleRate: 0.5,
debug: true,
version: "2.1.0",
debounceMs: 2000
)
)Test Your Integration
Start with a caught error. It uploads immediately and works with the Xcode debugger attached, so it is the fastest way to confirm the wiring:
import SwiftUI
import Traceway
struct TestError: Error {}
struct TracewayTestView: View {
var body: some View {
Button("Send Test Error") {
Traceway.capture(TestError())
Traceway.flush(timeout: 5)
}
}
}Tap it and check your Traceway dashboard. The error should appear on the Issues page within a few seconds.
To verify hard-crash capture as well, add a second button:
Button("Force Crash") {
fatalError("Test crash from Traceway integration")
}This one does nothing while you are running from Xcode. Hard crashes are intercepted with POSIX signal handlers, and when the debugger is attached lldb intercepts the signal first, so the SDK's handler never runs. Test it without the debugger: install once from Xcode, stop the debugger, launch the app from the home screen, tap the button, then relaunch and watch the report upload on the next launch.
Release Symbolication (dSYM upload)
A release build ships stripped, so crash traces arrive as bare image offsets with no function names or line numbers. Upload the build's .dSYM and Traceway symbolicates those traces server-side, turning each frame into function (file:line:col). You upload the raw dSYM; there is no client-side parsing.
The SDK ships an uploader script. Add an Xcode Run Script build phase that invokes it:
"$SRCROOT/path/to/Scripts/upload_symbols.sh"The script no-ops on non-Release builds and when the token is unset, so it is safe to leave in place. Set two environment variables for the phase:
TRACEWAY_UPLOAD_TOKEN: your project's source map / symbol upload token from the dashboard, the same one used for JavaScript source maps. It is not the runtime token in your connection string.TRACEWAY_URL: your Traceway base URL (or/api/reportURL); the script derives the upload URL from it.
See iOS symbolication for the full reference: the script flags, the raw HTTP upload contract for CI without Xcode, and how a non-symbolicated frame resolves into source.