iOS SDK

Native iOS SDK for screenshots, crash reporting, screen recording, session replay, and feature requests.

Installation

Download iOS SDK

Source package — add as a local Swift Package. Public registry coming soon.

Download .zip
Download sample app (SwiftUI demo project)

Swift Package Manager (local)

Unzip the download, then add as a local package in Xcode.

// Option A — Xcode UI // File > Add Package Dependencies > Add Local... // Select the unzipped mcpfeedback-ios-sdk/ folder // Option B — Package.swift dependencies: [ .package(path: "../mcpfeedback-ios-sdk"), ], targets: [ .target(name: "YourApp", dependencies: [ .product(name: "McpFeedback", package: "ios-sdk"), ]), ]

CocoaPods (local)

For projects that use CocoaPods as the dependency manager.

# Podfile — point to the unzipped folder pod 'McpFeedback', :path => '../mcpfeedback-ios-sdk'
pod install

Minimum iOS deployment target: 13.0  •  Xcode: 15+

PrivacyInfo.xcprivacy

The SDK bundle includes a PrivacyInfo.xcprivacy file declaring all API usage reasons required for App Store submission (camera access for annotation, photo library for screenshot, accelerometer for shake detection). You do not need to add your own entries for SDK-driven API usage.

Quick Start

Get your first feedback submission in under 5 minutes.

1

Install the SDK

Add via Swift Package Manager or CocoaPods.

Swift Package Manager
// Download the SDK zip from the iOS docs page, then:
// Xcode: File > Add Package Dependencies > Add Local...
// Select the unzipped mcpfeedback-ios-sdk/ folder

// Or in Package.swift:
.package(path: "../mcpfeedback-ios-sdk")
2

Get your API key

Create an account and generate a site key from your dashboard.

3

Initialize in AppDelegate or App struct

Initialize before the first view renders.

AppDelegate.swift / MyApp.swift
import McpFeedback

// UIKit — AppDelegate.swift
func application(_ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    McpFeedback.shared.initialize(
        siteKey: "your-site-key",
        config: McpFeedbackConfig(shakeEnabled: true)
    )
    return true
}

// SwiftUI — MyApp.swift
@main
struct MyApp: App {
    init() {
        McpFeedback.shared.initialize(
            siteKey: "your-site-key",
            config: McpFeedbackConfig()
        )
    }
    var body: some Scene { WindowGroup { ContentView() } }
}
4

Verify it works

Shake the device or simulator. Submit a test report and confirm it appears in your dashboard.

API Key Setup

Your site key is available in Dashboard > Settings > API Keys. Store it in your app's configuration — never in source control.

// Recommended: read from a .xcconfig or environment at build time. // Add to your Info.plist: // MCP_SITE_KEY = $(MCP_SITE_KEY) let siteKey = Bundle.main.object( forInfoDictionaryKey: "MCP_SITE_KEY" ) as? String ?? "" McpFeedback.shared.initialize(siteKey: siteKey)

Configuration

Pass a McpFeedbackConfig to McpFeedback.shared.initialize().

ParameterTypeDefaultDescription
siteKeyStringrequiredYour site identifier from the dashboard
apiBaseURLURL?nilCustom API base URL — defaults to production
shakeEnabledBooltrueEnable shake-to-report gesture
floatingButtonEnabledBooltrueShow persistent floating feedback button
screenshotDetectEnabledBooltrueDetect screenshot gesture and prompt feedback
edgePanEnabledBooltrueiOS-only: edge pan gesture from screen edge
twoFingerSwipeEnabledBoolfalseTwo-finger swipe up to trigger feedback
networkLoggingEnabledBooltrueAutomatically capture URLSession requests
crashReportingEnabledBooltrueCapture uncaught exceptions and submit on next launch
sessionReplayEnabledBoolfalseCapture UI-change screenshots as a replay timeline
privacyTierPrivacyTier.standard.strict | .standard | .relaxed — controls masking in replays
maxNetworkBodyBytesInt10240Max request/response body bytes captured per log entry
urlFilter[NSRegularExpression]?nilURL patterns to exclude from network logging

Screenshot Capture

The SDK uses UIGraphicsImageRenderer to capture the key window hierarchy as a PNG at the moment feedback is triggered. The SDK overlay is rendered after capture so it is never included in the screenshot.

// Manual capture: let screenshot = McpFeedback.shared.captureScreenshot() // Programmatic submission with screenshot: McpFeedback.shared.submit( FeedbackData( title: "Layout broken on profile screen", screenshot: screenshot ) )

Annotation Tools

The annotation editor renders via Core Graphics on a UIView overlay. Three tools:

  • Pen — freehand drawing with configurable color and stroke width
  • Highlight — translucent rectangle to draw attention to a region
  • Blur — blurs a rectangular region for privacy before upload

Invocation Methods

Seven ways to open the feedback form on iOS:

Shake to report

Default. Detects device shake via the motion event chain.

// shakeEnabled: true in McpFeedbackConfig (default)

Floating button

A UIWindow at .statusBar + 1 renders a persistent overlay button that never blocks touches.

floatingButtonEnabled: true // default

Screenshot detection

Listens for UIApplicationUserDidTakeScreenshotNotification and prompts for feedback.

screenshotDetectEnabled: true // default

Programmatic

Trigger from your own UI (Help menu, settings row, etc.).

McpFeedback.shared.show()
// or from a specific view controller:
McpFeedback.shared.show(from: self)

Two-finger swipe

Two-finger swipe upward gesture via UIGestureRecognizer added to the key window.

twoFingerSwipeEnabled: true

Edge pan (iOS only)

UIScreenEdgePanGestureRecognizer from the leading or trailing edge.

McpFeedbackConfig(
  edgePanEnabled: true,
  edgePanEdge: .right // .left | .right
)

Network Logging

The SDK swizzles URLSession via a custom URLProtocol subclass to intercept all HTTP traffic. The last N log entries are attached to each feedback report.

McpFeedbackConfig( networkLoggingEnabled: true, maxNetworkBodyBytes: 10240, urlFilter: [ try! NSRegularExpression(pattern: "analytics\."), try! NSRegularExpression(pattern: "/health"), ], redactHeaders: ["Authorization", "Cookie"] )

Crash Reporting

The SDK installs signal handlers and an NSUncaughtExceptionHandler to capture crashes. On next launch, queued crash reports are uploaded automatically. App Hang detection uses MetricKit on iOS 14+.

// Crash reporting is on by default. To disable: McpFeedbackConfig(crashReportingEnabled: false) // Manual error reporting: McpFeedback.shared.recordError(error, context: ["screen": "CheckoutView"]) // Record non-fatal: McpFeedback.shared.recordNonFatal( message: "Payment gateway returned unexpected status", severity: .high )

Each crash report includes: exception type, reason, call stack, device model, OS version, app version, free memory, disk space, and the last 20 network log entries.

Screen Recording

The SDK uses ReplayKit (RPScreenRecorder) for in-app screen recording. Recordings are MP4 (H.264), capped at 30 seconds by default.

McpFeedbackConfig( screenRecordingEnabled: true, maxRecordingDurationSeconds: 30, recordingQuality: .medium // .low | .medium | .high ) // Add to Info.plist if including microphone audio: // NSMicrophoneUsageDescription // "Used for optional audio in screen recordings" // Views that should be blurred in recordings: McpFeedbackMask { SensitiveView() }

ReplayKit requires the user to grant screen recording permission on first use via a system dialog. The SDK presents this dialog automatically when recording is initiated.

Session Replay

Session Replay captures lightweight UI-change screenshots assembled into a scrubable timeline in the dashboard.

McpFeedbackConfig( sessionReplayEnabled: true, privacyTier: .standard, // .strict | .standard | .relaxed replaySamplingInterval: 2.0, // seconds between frames replayMaxFrames: 120 )
Privacy TierBehavior
.strictMask all UILabel, UIImageView — only layout captured
.standardMask UITextField, UITextView, and manually marked views
.relaxedOnly mask views wrapped in McpFeedbackMask

Feature Requests

Present the in-app feature request board or submit requests programmatically.

// Show the feature request board: McpFeedback.shared.showFeatureRequests() // Programmatic submission: McpFeedback.shared.submitFeatureRequest( title: "Dark mode support", description: "App should respect system dark mode.", userEmail: "user@example.com" ) { result in switch result { case .success(let ref): print("Submitted: \(ref)") case .failure(let err): print("Error: \(err)") } }

Privacy Masking

Use McpFeedbackMask (SwiftUI) or view.mcpMask() (UIKit) to prevent views from appearing in screenshots, recordings, and replays.

// SwiftUI: McpFeedbackMask { CreditCardView(number: card.number) } // UIKit: cardLabel.mcpMask() // Password fields (UITextField with isSecureTextEntry = true) // are auto-masked regardless of privacy tier.

Offline Queue

All submissions are persisted to a local SQLite database (via GRDB.swift) before upload. The SDK retries with exponential backoff when connectivity is restored.

McpFeedbackConfig( offlineQueueMaxItems: 50, offlineQueueMaxAgeDays: 7 )

API Reference

The full API reference is auto-generated from Swift doc comments using swift-docc (DocC).

iOS API Reference

Auto-generated from source code comments — always up to date with the latest SDK version.

View iOS API Reference →

To regenerate locally: bash scripts/generate-api-docs.sh