iOS SDK

iOS

The Snapbug iOS SDK is built with Kotlin Multiplatform and distributed as SnapbugSDK.xcframework with a Swift-friendly wrapper. One call installs the full default plugin set: debug feedback overlay, network, analytics, crash reporter, device info, and logs.

Connections work over the Chrome Extension room-code flow (WebRTC, auto-enabled in debug builds) or directly over the local network. Simulators connect to localhost out of the box; physical devices use your machine's LAN IP as serverHost or the room-code flow. Only Apple-silicon simulators are supported (x86_64 simulator slices are excluded).

Installation

Add both lines to your Podfile, then run pod install:

pod 'Snapbug',       '~> 0.1.1', :configurations => ['Debug']
pod 'Snapbug-no-op', '~> 0.1.1', :configurations => ['Release']

Snapbug-no-op is the release twin: same import Snapbug API, every call inert. Your App Store build then ships neither the inspector nor the overlay, and you never guard the call site. See Release builds.

Initialization

Import the module and call Snapbug.start() once at app startup:

import Snapbug
 
@main
struct MyApp: App {
    // Optional — only needed for the Home Screen quick action (long-press the app icon
    // to open the Snapbug menu). Everything else works without it.
    @UIApplicationDelegateAdaptor(SnapbugAppDelegate.self) var snapbugDelegate
 
    init() {
        Snapbug.start()
    }
 
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

On CocoaPods you do not guard this call — the Release build links the no-op pod and Snapbug.start() does nothing there. If your app already has its own scene delegate, call Snapbug.handleShortcut(_:) from your own quick-action handler instead of adopting SnapbugAppDelegate.

Or with configuration:

import Snapbug
 
Snapbug.start(config: .init(
    serverHost: "192.168.1.42",           // LAN IP for physical devices; nil = localhost
    screenNameProvider: { MyRouter.currentScreen },
    appVersion: "1.0",
    catchFatalErrors: true                 // default
))

For UIKit-based apps:

import Snapbug
 
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        Snapbug.start()
        return true
    }
}

Release builds

Android has always had a no-op twin (snapbug-no-op) that turns the SDK into empty calls in release. iOS now has the same thing: the Snapbug-no-op pod. Same Objective-C surface, same Swift wrapper, every call inert, and module_name is still Snapbug — so import Snapbug compiles in both configurations and your code stays identical.

Declared with :configurations as shown above, this is what an App Store build gets:

Debug (live)Release (no-op)
Snapbug.framework in the bundle31 MB6.7 MB
Overlay shown to end usersyesno
Device registers with the inspectoryesno

The 31 MB is the Compose/Skia runtime the overlay is written in — not WebRTC. The published framework contains no WebRTC symbols at all; that transport is a separate snapbug-transport-webrtc module.

Both lines are required. Declaring only pod 'Snapbug', :configurations => ['Debug'] leaves the Release configuration without the Snapbug module, and the build fails to compile.

Supported Features

FeatureStatusNotes
Debug FeedbackSupportedOverlay, screenshots, annotations, bug reports — included in the same framework
Network (Ktor)SupportedInstall the Snapbug Ktor plugin in your shared KMP HttpClient
AnalyticsSupportedForward analytics events from Swift
Crash ReporterSupportedFatal error capture on by default (catchFatalErrors)
Device InfoSupportedDevice/OS metadata in the inspector
LogsSupportedReal-time stdout/stderr capture — see below
Deep LinksNot installed by default
Database / SharedPreferences / Tables / FilesNot available on iOS

Logs

Snapbug.start() installs the logs plugin, which captures the process stdout/stderr (Swift print, NSLog), mirrors it back to the Xcode console, and streams every line into the Logs inspector:

  • print → level I, tag stdout
  • NSLog → level W, tag stderr (the standard NSLog date prefix is stripped)
  • os_log / os.Logger write past stdio and are not captured

Network Plugin (Ktor)

To capture network traffic from a Ktor client, install the plugin in your shared Kotlin Multiplatform code:

val client = HttpClient {
    install(SnapbugKtorPlugin)
}

Analytics

Forward analytics events from Swift:

import Snapbug
 
SnapbugAnalyticsHelper.shared.sendEvent(
    trackerName: "firebase",
    eventName: "screen_view",
    properties: ["screen_name": "Home"]
)

Limitations

  • No release twin on SPMSnapbug-no-op is a CocoaPods-only pod, because SPM has no equivalent of :configurations. On the SPM path, guard Snapbug.start() with #if DEBUG yourself
  • KMP naming — the SDK is a Kotlin Multiplatform framework, so some low-level APIs use Kotlin-style naming conventions
  • Apple-silicon simulators onlyx86_64 simulator slices are excluded (EXCLUDED_ARCHS[sdk=iphonesimulator*] = i386 x86_64)

Sample Project

A complete Swift/SwiftUI sample app is available at sample-ios-swift/ in the repository:

  1. Build the XCFramework: ./scripts/build-xcframework.sh (runs :debug-feedback:assembleSnapbugSDKReleaseXCFramework and copies the result into the Swift package).
  2. Open sample-ios-swift/SampleApp.xcodeproj in Xcode.
  3. Select an iOS Simulator target, build and run.

Next Steps