iOS apps crash. Your users report crashes to the App Store, leave one-star reviews, or just uninstall silently. The problem isn't crashes — it's that you don't hear about them until the damage is done. iOS error tracking changes that: every crash lands in your dashboard the moment it happens, with a full stack trace, the affected user, and the exact release that introduced the bug. This guide walks you through setting up production-grade error tracking in your iOS app using the Sentry SDK pointed at LightTrace.
By the end, you'll capture unhandled exceptions and crashes in Swift and Objective-C, upload symbol files so stack traces point to your real code, and monitor crash-free rate across releases. Your team will fix crashes before users discover them.
Install and initialize the Sentry SDK
Start by adding the SDK to your project. If you're using CocoaPods:
pod 'Sentry', :git => 'https://github.com/getsentry/sentry-cocoa.git', :tag => '8.0.0'
Or if you're using Swift Package Manager, add it to your Package.swift or through Xcode's dependency manager.
Once installed, initialize the SDK early in your app lifecycle — in application(_:didFinishLaunchingWithOptions:) — with your LightTrace DSN:
import Sentry
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
SentrySDK.start { options in
options.dsn = "https://<key>@your-lighttrace-host/1"
options.environment = "production"
options.releaseName = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String
options.tracesSampleRate = 1.0
}
return true
}
That's it. From this point forward, every unhandled exception, crash, and assertion failure is automatically captured and sent to LightTrace. The SDK hooks into the runtime's crash handlers without any additional wrapping.
The Sentry SDK for iOS is compatible with Swift and Objective-C. The initialization looks the same in both; if you're on Objective-C, use the ObjC syntax.
Why dSYM symbolication matters
When your iOS app crashes in production, the stack trace contains memory addresses, not code. Without symbolication, you see:
Thread 0 Crashed:
0 MyApp 0x000000010010a234 0x100100000 + 106036
1 UIKit 0x00007fff4a5c1a12 -[UIViewController viewDidLoad] + 42
The first frame is useless. That 0x000000010010a234 address means nothing without the symbol file. That's where dSYM (debug symbol) files come in.
When you build your iOS app for release, Xcode generates a .dSYM bundle. This file maps every memory address back to its original function name and source file. Once LightTrace has your dSYM, the same crash appears as:
Thread 0 Crashed:
0 MyApp PaymentViewController.swift line 45 in processPayment(_:)
1 UIKit -[UIViewController viewDidLoad]
Suddenly you know exactly which function, file, and line crashed. No guessing, no hunting through Instruments.
Upload dSYM files to LightTrace
Your build needs to upload dSYM files each time you ship a release. The easiest way is with the LightTrace API and a build phase script.
First, add a build phase to your target. In Xcode, go to Build Phases → + → New Run Script Phase, and add this script:
DWARF_DSYM_FOLDER_PATH="$BUILD_DIR/$DWARF_DSYM_FOLDER_NAME"
DWARF_DSYM_FILE_NAME="$EXECUTABLE_NAME.app.dSYM"
DWARF_DSYM_PATH="$DWARF_DSYM_FOLDER_PATH/$DWARF_DSYM_FILE_NAME"
if [[ ! -d "$DWARF_DSYM_PATH" ]]; then
echo "dSYM not found at $DWARF_DSYM_PATH. Skipping upload."
exit 0
fi
curl -X POST https://your-lighttrace-host/api/releases/uploads/ \
-H "Authorization: Bearer $LIGHTTRACE_API_KEY" \
-F file=@"$DWARF_DSYM_PATH" \
-F release="$MARKETING_VERSION"
Store your API key as a build setting (not hardcoded) so it never lands in version control. After each build, the script uploads the dSYM for your new release automatically.
Run this script only for release builds. Add a conditional to skip it during development: if [[ "$CONFIGURATION" == "Release" ]]; then ... fi.
Monitor crash-free rate and release health
iOS crashes are more visible than web errors — users feel them. That's why crash-free rate is the metric that predicts app retention. A 1% drop in crash-free sessions can cost you measurable churn.
Set your release when you initialize the SDK (as shown above), and LightTrace will automatically calculate your crash-free rate — the percentage of sessions that went crash-free. Pair this with release health monitoring to see if a new release introduced a regression:
// Tag events with user info for better grouping
SentrySDK.setUser(SentryUser(userId: user.id))
// Add breadcrumbs to track the path to a crash
SentrySDK.addBreadcrumb(SentryBreadcrumb(
category: "navigation",
message: "User navigated to checkout",
level: .info
))
Now when a crash happens, LightTrace knows which release introduced it, how many sessions were affected, and the exact path the user took before crashing. A regression in one release jumps out immediately.
Handle background crashes and crashes in frameworks
The Sentry SDK captures crashes across your entire app — in background tasks, in framework code, and in third-party libraries. If your app uses URLSession, Core Data, or background fetch, every crash there is captured automatically.
For custom logic you want to track explicitly, use SentrySDK.captureException(_:):
do {
try performRiskyOperation()
} catch {
SentrySDK.captureException(error)
}
You can also set context at runtime to enrich crashes:
SentrySDK.configureScope { scope in
scope.setContext(
value: [
"api_version": "v3",
"feature_flag_cohort": "treatment_b"
],
key: "app"
)
}
This context appears in every crash going forward, making it easier to connect a crash to a feature, an API version, or a user cohort.
Scrubbing sensitive data
iOS crash reports can leak passwords, API keys, PII, or payment info. Before dSYM data and event context reach LightTrace's servers, the SDK can scrub sensitive data:
SentrySDK.start { options in
options.dsn = "https://<key>@your-lighttrace-host/1"
options.beforeSend = { event in
// Remove query strings from URLs
if var request = event.request {
request.url = request.url?.components(separatedBy: "?").first
event.request = request
}
return event
}
}
This pattern lets you strip URLs, redact headers, or filter breadcrumbs before they leave the device — keeping your crash data safe without losing debugging context.
Next steps: add tracing across your service
Error tracking solves the "what broke" question. If your iOS app talks to a backend, you may also want to trace the full request path — from user action to your server and back — to catch slow endpoints or failed API calls. See add error tracking to any app for the universal pattern, and check out what is error tracking if you're new to the concept.
Start tracking errors in minutes
Point the Sentry SDK at LightTrace and start capturing iOS crashes with full symbolication and crash-free tracking — free up to 5,000 events a month.
iOS crash tracking is table stakes for any app in production. Every crash your team knows about before your users do is a chance to ship a fix, keep your app stable, and stay off the one-star reviews. Add error tracking to your next release.