iOS

The Middleware iOS RUM SDK collects user activity, application performance data, and errors from iOS applications. It helps you investigate crashes, slow screens, and failed requests in the context of a user session.

Collected data includes crashes, slow or frozen frames, network requests, and sessions. Session Replay adds visual context; correlation with backend traces helps follow a request beyond the mobile application when backend instrumentation is configured.

Prerequisites#

Before installing the SDK, make sure you have:

  • iOS 13 or later.
  • Xcode with Swift Package Manager support.
  • A Middleware account and RUM application credentials.
  • Access to your iOS application source code.
  • HTTPS connectivity to your Middleware ingestion endpoint.

The SDK also supports macOS 10.15+ and tvOS 13+.

To check available SDKs in Xcode, run:

shell
xcodebuild -showsdks

Installation#

1 Create a RUM application#

  1. Log in to Middleware.
  2. Go to Installation → RUM.
  3. Select iOS as the platform.
  4. Click New Application.
  5. Enter your application name and click Create Application.
  6. Copy the generated RUM access token and target URL.

2 Install the iOS SDK#

You can install the Middleware iOS SDK using Swift Package Manager or CocoaPods.

In Xcode:

  1. Open your iOS project.
  2. Go to File → Add Package Dependencies.
  3. Enter the repository URL: https://github.com/middleware-labs/middleware-ios
  4. Select version 2.3.2 or a compatible newer version.
  5. Add the package to your application target.

For projects using Package.swift, add:

swift
.package(
    url: "https://github.com/middleware-labs/middleware-ios",
    from: "2.3.2"
)

Add the Middleware specs repo and the CocoaPods CDN to the top of your Podfile:

ruby
source 'https://github.com/middleware-labs/cocoapods-specs.git'
source 'https://cdn.cocoapods.org/'

Keep both sources: new MiddlewareRum versions are published to the Middleware repo, and the SDK's dependencies still come from the CocoaPods CDN. CocoaPods trunk stops accepting new pods on December 2, 2026, so without the Middleware source your app stays on the last version published to trunk.

Add the following dependency to your Podfile:

ruby
pod 'MiddlewareRum', '~> 2.3'

Install the dependency:

bash
pod install

Note: MiddlewareRum is a static framework. If your project uses use_frameworks!, ensure dependent pods are linked statically.

3 Initialize Middleware#

Initialize the SDK as early as possible in your application's lifecycle to capture initial screens and application activity.

Choose the setup based on your application architecture.

For SwiftUI applications, initialize Middleware in your application's App initializer.

swift
import SwiftUI
import MiddlewareRum

@main
struct MyApp: App {

    init() {
        do {
            try MiddlewareRumBuilder()
                .target("https://<MW_UID>.middleware.io")
                .rumAccessToken("<MW_RUM_ACCESS_TOKEN>")
                .serviceName("my-ios-app")
                .projectName("My-iOS-App")
                .deploymentEnvironment("PROD")
                .globalAttributes([
                    "app.version": "1.0.0"
                ])
                .build()
        } catch {
            print("Middleware RUM initialization failed: \(error)")
        }
    }

    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

For UIKit applications, initialize Middleware inside AppDelegate.

swift
import UIKit
import MiddlewareRum

@main
class AppDelegate: UIResponder, UIApplicationDelegate {

    func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions:
            [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {

        do {
            try MiddlewareRumBuilder()
                .target("https://<MW_UID>.middleware.io")
                .rumAccessToken("<MW_RUM_ACCESS_TOKEN>")
                .serviceName("my-ios-app")
                .projectName("My-iOS-App")
                .deploymentEnvironment("PROD")
                .globalAttributes([
                    "app.version": Bundle.main.object(
                        forInfoDictionaryKey: "CFBundleShortVersionString"
                    ) as? String ?? ""
                ])
                .build()
        } catch {
            print("Middleware RUM initialization failed: \(error)")
        }

        return true
    }
}

Replace the placeholders with your Middleware credentials.

ParameterRequiredDescription
targetYesMiddleware ingestion endpoint
rumAccessTokenYesRUM access token generated during setup
serviceNameYesService name used to identify the application
projectNameYesProject name associated with the application
deploymentEnvironmentNoEnvironment, such as PROD or DEV
globalAttributesNoCustom attributes such as application version

Note: If your application requires user consent before collecting telemetry, initialize the SDK only after consent is granted.

4 Run and verify#

Build and run your application on an iOS simulator or physical device.

  1. Open the application.
  2. Navigate between screens and trigger a few network requests.
  3. Go to RUM → Session Explorer in Middleware.
  4. Verify that your application sessions appear.

Read more about RUM explorer and see what data to monitor for frontend performance.

Enable or disable monitoring features#

Crash reporting, HTTP instrumentation, and slow rendering detection are enabled by default.

To disable specific features, add the corresponding methods during initialization:

swift
try MiddlewareRumBuilder()
    .target("https://<MW_UID>.middleware.io")
    .rumAccessToken("<MW_RUM_ACCESS_TOKEN>")
    .serviceName("my-ios-app")
    .projectName("My-iOS-App")
    .disableCrashReportingInstrumentation()
    .disableNetworkMonitoring()
    .disableSlowRenderingDetection()
    .build()

Only include the disable methods for features you don't want to collect.

MethodDescription
disableCrashReportingInstrumentation()Disables automatic crash reporting
disableNetworkMonitoring()Disables HTTP request instrumentation
disableSlowRenderingDetection()Disables slow and frozen frame detection
slowFrameDetectionThresholdMs(Double)Configures the slow frame threshold; default is 16.7 ms
frozenFrameDetectionThresholdMs(Double)Configures the frozen frame threshold; default is 700 ms

Configure Session Replay#

Session Replay is enabled by default and starts automatically when the SDK initializes.

It records user activity and screen changes to help investigate application issues.

Configure recording quality and privacy#

Use RecordingOptions to configure recording frequency, quality, and masking.

swift
try MiddlewareRumBuilder()
    .target("https://<MW_UID>.middleware.io")
    .rumAccessToken("<MW_RUM_ACCESS_TOKEN>")
    .serviceName("my-ios-app")
    .projectName("My-iOS-App")
    .recordingOptions(
        RecordingOptions()
            .setFrequency(.standard)
            .setQuality(.standard)
            .setMaskAllTextInputs(true)
            .setMaskAllImages(true)
    )
    .build()
OptionDescription
setFrequency()Recording frequency: low, standard, or high
setQuality()Recording quality: low, standard, or high
setMaskAllTextInputs()Masks text input values; enabled by default
setMaskAllImages()Masks images; enabled by default

Disable Session Replay#

To collect RUM telemetry without recording user sessions, add:

swift
.disableRecording()

Session recording limits#

  • Maximum session duration: 4 hours.
  • Idle timeout: 15 minutes.
  • Default: Session Replay enabled.

After the idle timeout, new user activity starts a new session.

Mask sensitive information#

Middleware masks sensitive text inputs and images by default. You can also mask specific UI elements that contain payment details, authentication information, or other sensitive content.

SwiftUI#

Use the .sensitive() modifier:

swift
Text("Sensitive account information")
    .sensitive()

UIKit#

Exclude a view from Session Replay:

swift
MiddlewareRum.addIgnoredView(sensitiveView)

Alternatively, mark a view using its accessibility identifier:

swift
cardNumberField.accessibilityIdentifier = "mw-no-capture"

Supported identifiers:

  • mw-no-capture — Always masks the view.
  • mw-no-mask — Excludes the view from masking.

Important: Secure text fields and sensitive textContentType fields, such as passwords, credit card details, and one-time codes, remain masked regardless of the configuration.

Masking is applied on the device before session recording data is uploaded.

Configure distributed tracing#

Distributed tracing connects iOS network requests with backend APM traces.

The SDK automatically instruments URLSession and injects W3C traceparent headers into outgoing requests.

No additional HTTP client instrumentation is required.

Prerequisites#

  • Middleware APM instrumentation must be enabled on your backend.
  • Backend services must support W3C Trace Context.
  • Network monitoring must be enabled in the iOS SDK.

Restrict trace propagation targets#

By default, trace headers are added to outgoing requests, excluding Middleware ingestion endpoints.

To restrict propagation to your backend domains:

swift
try MiddlewareRumBuilder()
    .target("https://<MW_UID>.middleware.io")
    .rumAccessToken("<MW_RUM_ACCESS_TOKEN>")
    .serviceName("my-ios-app")
    .projectName("My-iOS-App")
    .tracePropagationTargets([
        "api\\.example\\.com",
        "checkout\\.example\\.com"
    ])
    .build()

Requests to other domains are still monitored but do not receive tracing headers.

Passing an empty array disables trace propagation.

Verify trace correlation#

  1. Open your application and trigger a backend API request.
  2. Go to RUM → Session Explorer.
  3. Open the session and select the network request.
  4. Follow the associated backend trace.

If the request has a trace ID but no backend spans, verify that your backend is instrumented and accepts W3C Trace Context.

Add custom logs and errors#

Custom logs#

Use the SDK to capture application-specific logs:

swift
MiddlewareRum.info("User opened checkout")
MiddlewareRum.debug("Loading payment details")
MiddlewareRum.warning("API response delayed")
MiddlewareRum.error("Payment request failed")
MiddlewareRum.critical("Unexpected application failure")

Report custom errors#

Record application errors for investigation:

swift
MiddlewareRum.addError("Unable to process payment")

Report handled exceptions#

Application crashes are captured automatically. You can report handled exceptions manually:

swift
MiddlewareRum.addException(
    e: NSException(
        name: NSExceptionName(rawValue: "RuntimeException"),
        reason: "Payment processing failed"
    )
)

Add custom attributes#

Use global attributes to filter sessions by application version, environment, or user group.

swift
MiddlewareRum.setGlobalAttributes([
    "app.version": "1.0.0",
    "user.type": "premium"
])

Prefer stable, non-sensitive values. Avoid sending passwords, tokens, or personal information.

Set a custom screen name#

To identify screens using application-specific names:

swift
MiddlewareRum.setScreenName("checkout")

This is useful when investigating navigation or grouping events by screen.

Instrument WebView content#

If your application uses a WKWebView, you can connect Browser RUM with Mobile RUM to investigate hybrid user journeys.

swift
MiddlewareRum.integrateWebViewWithBrowserRum(view: webView)

Use this on the active WebView instance.

The embedded web application should also have the Middleware Browser RUM SDK installed for browser-side telemetry.

Configuration reference#

All methods accepted by MiddlewareRumBuilder():

MethodDescription
target(String)Sets the Middleware ingestion endpoint
rumAccessToken(String)Sets the RUM access token
serviceName(String)Sets the application service name
projectName(String)Sets the project name
deploymentEnvironment(String)Sets the deployment environment
globalAttributes(...)Adds custom attributes during initialization
tracePropagationTargets([String])Restricts trace propagation to selected URLs
recordingOptions(...)Configures Session Replay
disableRecording()Disables Session Replay
disableCrashReportingInstrumentation()Disables automatic crash reporting
disableNetworkMonitoring()Disables HTTP instrumentation
disableSlowRenderingDetection()Disables slow and frozen frame detection
slowFrameDetectionThresholdMs(Double)Sets the slow frame threshold
frozenFrameDetectionThresholdMs(Double)Sets the frozen frame threshold

Troubleshooting#

No RUM data appears#

If your application is running but telemetry does not appear:

  • Verify that the SDK is installed and imported correctly.
  • Confirm that MiddlewareRumBuilder().build() runs during application startup.
  • Check the RUM access token and target URL.
  • Verify that the device can connect to Middleware over HTTPS.
  • Review the Xcode console for initialization or export errors.

Network requests are missing#

If sessions appear but HTTP requests are not collected:

  • Confirm that disableNetworkMonitoring() is not enabled.
  • Verify that requests use URLSession or a networking library built on it.
  • Check whether the requests are sent to excluded Middleware ingestion endpoints.

Backend traces are not correlated#

If network requests appear but backend traces are missing:

  • Verify that backend APM instrumentation is enabled.
  • Confirm that the backend accepts W3C Trace Context.
  • Check that tracePropagationTargets() matches your backend domains.
  • Ensure that proxies or gateways do not remove the traceparent header.

Session Replay is missing#

If sessions appear without recordings:

  • Verify that disableRecording() is not enabled.
  • Check that SDK initialization completes successfully.
  • Confirm that recording is permitted by your application's consent settings.
  • Review SDK logs for recording or upload errors.

Sensitive information appears in recordings#

  • Verify that text and image masking is enabled.
  • Use .sensitive() for SwiftUI views.
  • Use MiddlewareRum.addIgnoredView() for UIKit views.
  • Mark sensitive fields with mw-no-capture.
  • Review masking whenever the application UI changes.

High slow or frozen frame counts#

The SDK reports:

  • Slow frames: Rendering time above 16.7 ms.
  • Frozen frames: Rendering time above 700 ms.

Use Xcode Instruments, including Time Profiler and Core Animation, to identify expensive main-thread work or rendering operations.

HTTPS requests are blocked#

iOS App Transport Security (ATS) blocks cleartext HTTP connections by default.

Use HTTPS for your Middleware ingestion endpoint and backend APIs. For development environments requiring HTTP, configure scoped ATS exceptions in Info.plist.

Build errors#

  • If Xcode can't resolve the package, go to File → Packages → Reset Package Caches and resolve again.
  • For CocoaPods, run pod install and open the .xcworkspace file, not the .xcodeproj.
  • If CocoaPods can't find or upgrade MiddlewareRum, check both sources are in your Podfile and run pod update MiddlewareRum.
  • If your Podfile uses use_frameworks!, link MiddlewareRum statically.
  • Verify that the deployment target is iOS 13 or later.

If the issue persists, contact Middleware Support at support@middleware.io.

Need assistance or want to learn more about Middleware? Get in touch with us via our Contact Us or join our Slack channel.

What did you think of this content?