2026-10-31 23:39:07 +03:00
2026-10-31 23:39:07 +03:00
2026-10-30 15:07:27 +03:00
2026-10-31 23:39:07 +03:00
2026-10-30 15:07:27 +03:00
2026-10-31 23:39:07 +03:00

Insight iOS SDK Developer Guide

This document describes the integration of the Insight iOS SDK with your iOS application.

Introduction

Insight iOS SDK collects location information and event data to track user interactions within the iOS application where it's installed. This data can be used for analyzing user behavior, improving user experience, and generating insights.

Table of Contents

1. Quick start

Get up and running with Insight SDK in 5 minutes:

Add the SDK

Via CocoaPods:

pod 'InsightSDK', :git => 'https://insight-dl.apps.sccc.sa/sccc/iOS-SDK-test.git'

Add required frameworks

(see Integration section)

Configure location permissions (optional)

(see Configuring permissions)

Initialize the SDK

UIKit

// In AppDelegate.swift
import InsightSDK

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    let sdkConfig = SdkConfiguration(
        apiKey: "YOUR_SECRET_KEY_HERE"
    )

    Insight.shared.start(config: sdkConfig, user: nil)
    return true
}

SwiftUI

Create AppDelegate.swift with initialization code

Add

@UIApplicationDelegateAdaptor private var appDelegate: AppDelegate

to your App struct.

For complete setup instructions, continue reading below.

2. Requirements

In order to integrate the Insight iOS SDK, make sure you are:

  • Targeting iOS version 15 or higher

  • Targeting the Swift 5 compiler

  • Registered on the Insight Portal

    • You need to create a Insight Access Key for the iOS platform if not created already.

Note: Make sure that you declare that "your app uses IDFA" on App Store Connect if you are using IDFA integration. Otherwise, your app may be rejected on review. Insight iOS SDK collects IDFA from the device when permitted by the user, in full compliance with the Apple requirements. Insight doesn't trigger the permission dialog; you need to trigger this if needed.

3. Integration

Adding the Insight iOS SDK

The Insight iOS SDK can be added via Swift Package Manager, CocoaPods, or manually.

Swift Package Manager installation

Add package dependency

In Xcode, go to File → Add Package Dependencies...

Enter repository URL

Enter the following URL in the search field:

https://insight-dl.apps.sccc.sa/sccc/iOS-SDK-test.git
Configure package

Select the version and version rule (recommended: "Up to Next Major Version") and add the package to your target.

CocoaPods installation

Referencing the InsightSDK pod in the Podfile will be sufficient to add the Insight iOS SDK to your project.

Create Podfile

If your project doesn't have a Podfile, then you can create one by running the following command on the terminal:

pod init
Reference InsightSDK in Podfile

Reference InsightSDK in the Podfile:

pod 'InsightSDK', :git => 'https://insight-dl.apps.sccc.sa/sccc/iOS-SDK-test.git'
Install pods

Install pods by running the following command on the terminal:

pod install

Manual installation

Download the SDK

You can download the SDK from the following repository:

https://insight-dl.apps.sccc.sa/sccc/iOS-SDK-test.git
Copy the xcframework

Copy "InsightSDK.xcframework" folder by dragging and dropping into your app using project navigator in Xcode. After copying the xcframework into your app, the color of the xcframework shall be blue.

Mark Embed and Sign

Go to project settings "Frameworks, Libraries and Embedded Content" section. Choose "Embed & Sign" for InsightSDK.xcframework.

Adding required frameworks

Insight iOS SDK utilizes the following frameworks. Please make sure that your project references all of them:

  • AdSupport.framework
  • CoreLocation.framework
  • CoreTelephony.framework
  • SystemConfiguration.framework

Configuring permissions

The SDK asks the user for no permission. Your app decides whether to ask for location and notification permissions, and the SDK uses a permission only after the user grants it. Location is optional: without it the SDK works and sends no location.

If your app asks for location permission, Apple requires two things:

  1. A purpose string in Info.plist for each kind of location permission your app requests: NSLocationWhenInUseUsageDescription, and NSLocationAlwaysAndWhenInUseUsageDescription if you also request Always. Without it, iOS shows the user no prompt, and App Store Connect can reject the build.
  2. Location in your app's privacy declarations. The SDK sends the device location to Insight once the user allows it. Declare Precise Location, linked to the user, for analytics, in your app's privacy manifest (PrivacyInfo.xcprivacy) and in the App Privacy details in App Store Connect.

With Always permission, the SDK also receives location updates while your app is in the background. In the subsections below, we provide sample description text.

Always and when in use

This descriptor is used for iOS 11 and later. It provides permission for both when in use and when killed.

Sample Text: "This application uses your location in order to inform you about interesting offers nearby. We advise you to choose the Always option to get the offers even when you are not using the application!"

You can insert it into your Info.plist file in the following syntax.

<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string><# insert always and when in use usage description text #></string>

When in use

This descriptor is used in all iOS versions. It provides permission for only when the application is in use. We advise you to warn your users about very low performance when receiving nearby offers.

Sample Text: "This application uses your location in order to inform you about interesting offers nearby. Allowing location when in use only may result in poor performance in finding nearby offers!"

You can insert it into your Info.plist file in the following syntax.

<key>NSLocationWhenInUseUsageDescription</key>
<string><# insert when in use usage description text #></string>

4. Usage

In order to utilize the capabilities of the Insight iOS SDK, it needs to be started at some point in your application's lifecycle.

Entering the Insight Platform Access Key

Insight iOS SDK requires the Insight Platform Access Key. You may need to create one for the iOS platform at the Insight Publisher Portal. If you do not have an account at the Insight Publisher Portal, please contact us at sdk@insight.apps.sccc.sa. You can set your key in your application's Info.plist file with the Insight Platform Access Key key:

<key>Insight Platform Access Key</key>
<string>YOUR_SECRET_KEY_HERE</string>

Alternatively, you can provide the Insight Platform Access Key via the SDK start method as documented in the next section.

UIKit apps

For traditional UIKit applications, initialize the SDK in your AppDelegate.swift:

import UIKit
import InsightSDK

@UIApplicationMain
class AppDelegate: NSObject, UIApplicationDelegate {

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

    func startInsightSDK() {
        let sdkConfig = SdkConfiguration(
            apiKey: "YOUR_SECRET_KEY_HERE"
        )

        // If you have a "User" class/struct you need to use "InsightSDK.User" to prevent the conflict
        let sdkUser = User(
            userId: "YOUR_APP_USERS_UNIQUE_IDENTIFIER_FOR_YOUR_PLATFORM_HERE",
            gender: YOUR_APP_USERS_GENDER_HERE, // .female or .male
            yearOfBirth: YOUR_APP_USERS_BIRTH_YEAR_HERE,
            displayName: "YOUR_APP_USERS_USERNAME_HERE",
            email: "YOUR_APP_USERS_EMAIL_HERE",
            phoneNumber: "YOUR_APP_USERS_PHONE_NUMBER_HERE",
            other: [
                "sp1" : "special property 1 value",
                "sp2" : "special property 2 value"
            ]
        )

        Insight.shared.start(config: sdkConfig, user: sdkUser, completion: { sdkState in
            switch sdkState {
            case .success:
                debugPrint("InsightSDK version: \(Insight.shared.version) started")

            case .skipped:
                debugPrint("InsightSDK version: \(Insight.shared.version) start skipped")

            case .failure:
                debugPrint("InsightSDK version: \(Insight.shared.version) failed")

            @unknown default:
                debugPrint("InsightSDK version: \(Insight.shared.version) start state unknown")
            }
        })
    }
}

Simple initialization

You can start the Insight iOS SDK by simply invoking the start method of the shared instance:

import InsightSDK

let sdkConfig = SdkConfiguration(
    apiKey: "YOUR_SECRET_KEY_HERE"
)
Insight.shared.start(config: sdkConfig, user: nil)

SwiftUI apps

For SwiftUI applications (iOS 14+), you need to create an AppDelegate.swift file and use @UIApplicationDelegateAdaptor to ensure the SDK initializes properly.

Create AppDelegate.swift

Create a new file called AppDelegate.swift with your SDK initialization:

import UIKit
import InsightSDK

// AppDelegate to handle lifecycle events
class AppDelegate: NSObject, UIApplicationDelegate {
    let insightSDK = InsightSDKManager()

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

Create an SDK manager to access SDK easier:

import SwiftUI
import InsightSDK

class InsightSDKManager: ObservableObject {

    @Published var insightSDKStatus: String = "..."

    func startInsightSDK() {
        let sdkConfig = SdkConfiguration(
            apiKey: "YOUR_SECRET_KEY_HERE",
            pushToken: "" // when you don't have a push token use empty string
        )

        Insight.shared.start(config: sdkConfig, user: nil, completion: { [weak self] sdkState in
            guard let self else { return }
            DispatchQueue.main.async {
                switch sdkState {
                case .success:
                    self.insightSDKStatus = "Started"
                    debugPrint("InsightSDK version: \(Insight.shared.version) started")

                case .skipped:
                    self.insightSDKStatus = "Skipped"
                    debugPrint("InsightSDK version: \(Insight.shared.version) start skipped")

                case .failure:
                    self.insightSDKStatus = "Failed"
                    debugPrint("InsightSDK version: \(Insight.shared.version) failed")

                @unknown default:
                    self.insightSDKStatus = "Unknown"
                    debugPrint("InsightSDK version: \(Insight.shared.version) start state unknown")
                }
            }
        })
    }
}

Connect AppDelegate to the SwiftUI app

In your main SwiftUI App file, add the @UIApplicationDelegateAdaptor:

import SwiftUI

@main
struct MyApp: App {
    @UIApplicationDelegateAdaptor private var appDelegate: AppDelegate

    var body: some Scene {
        WindowGroup {
            ContentView()
                .environmentObject(appDelegate.insightSDK)
        }
    }
}

Configuration options

SdkConfiguration parameters

The SdkConfiguration class contains the following properties:

Property Type Description
apiKey String API Key generated in Insight Platform for the app.
pushToken String? Push notification token for the device.
logLevel LogLevel Logging verbosity level (default: .error).

User parameters

The user parameter allows you to enhance the audience data by providing information about the primary user (subscriber) of your application. You can give any information that makes the subscriber unique in your application's understanding. The User class contains the following:

Property Type Example Description
userId String? "42" Unique identifier of the user
gender UserGender? .female Gender of the user (.female or .male)
yearOfBirth Int? 1999 Year of birth of the user
email String? "mail@me.com" Email address of the user
displayName String? "John Doe" Display name of the user
phoneNumber String? "+96653612345" Mobile phone number of the user
isPIIHashed Bool? true Whether to hash user info
other Dictionary<String,String>? ["key": "value"] Extra information for the user

Note: email and phoneNumber details are never sent in plain-text to the Insight Platform if the isPIIHashed property is set to true (default true). These values are always irreversibly hashed so that no personally identifiable information is stored.

Completion handler

The completion parameter allows you to execute your business logic after the Insight iOS SDK initialization succeeds or fails.

Stopping, restarting and changing configuration

start(config:user:completion:) covers the first launch. A settings screen that changes the user or the API key needs the calls below. Call each of them on Insight.shared.

Stopping

stop() and stop(completion:) return at once. From the call, the SDK collects nothing. Event logging, crash reporting, location monitoring, screen tracking, network performance tracking and screen recording stop. An event that you log answers its callback with an APIError whose code is -4, and the SDK does not store it.

Then the SDK sends what it holds for at most 5 seconds, in the background. It sends the stored crash reports first, then the queued events and the queued screen recordings together. Whatever did not leave stays queued and goes out after your next start. The stop deletes nothing.

stop(completion:) calls completion once, on the main queue, when the SDK has sent what it could. This happens at most 5 seconds after the call, or at once when the SDK was not started. The SDK does not cancel a request that is still in progress at 5 seconds. A second stop before the report joins the first and gets the same report. A start or restart that you call before the report waits for it and runs after it. After the report, the SDK sends nothing until your next start succeeds.

For screen recording, a stop ends the open recording and adds its last part to the queue that the stop sends. The next start turns screen recording on again.

import InsightSDK

Insight.shared.stop(completion: {
    debugPrint("InsightSDK stopped")
})

Changing the user

The SDK sends the User when a session starts. To send a changed user, such as a new display name, call restart(user:config:) with the new User. The SDK stops, waits for the stop's report and starts again with the new User. A call to stop() and then to start(config:user:completion:) does the same, because the start waits for the stop's report.

import InsightSDK

let sdkUser = User(
    userId: "YOUR_APP_USERS_UNIQUE_IDENTIFIER_FOR_YOUR_PLATFORM_HERE",
    gender: YOUR_APP_USERS_GENDER_HERE, // .female or .male
    displayName: "YOUR_APP_USERS_NEW_USERNAME_HERE"
)

Insight.shared.restart(user: sdkUser)

Changing the API key

To use a new API key, pass a new SdkConfiguration to restart(user:config:). The SDK stops, then starts with the new configuration once the stop has reported. The change deletes nothing. New events, crash reports and screen recordings go out with the new key. What the SDK queued under the old key keeps going out with the old key.

import InsightSDK

let sdkConfig = SdkConfiguration(
    apiKey: "YOUR_NEW_SECRET_KEY_HERE"
)
Insight.shared.restart(config: sdkConfig)

Restarting

restart(user:config:) stops the SDK and starts it again once the stop has reported. Both parameters are optional. A nil user or configuration means the one from the most recent start. When the SDK is not running, restart only starts it. The stop sends what the SDK holds for at most 5 seconds and keeps the rest, as Stopping describes.

Events that your app logs between the restart call and the end of the new start wait in memory, in order. When the start ends, the SDK logs them. If event logging is off at that time, each of them gets the error -4. A plain stop() still refuses events with -4.

import InsightSDK

Insight.shared.restart()

Clearing stored data

Each method below erases one part of what the SDK keeps on the device. None of them calls stop(). Call each of them on Insight.shared:

Method What it clears What it keeps
clearStoredData() The stored crash reports and every stored screen recording. It also stops a recording upload in progress. Queued events and health messages.
clearCrashReports() The stored crash reports. Everything else, screen recordings included.
clearHealthMessages() The messages that you logged with logHealthMessage(_:). Everything else.
clearScreenRecordings() Every stored screen recording and its upload queue. It also stops an upload in progress. It works before start. Everything else.
clearRequestQueues() Every queued event that waits for upload, for every API key. Everything else, screen recordings included.

clearStoredData() and clearScreenRecordings() wait for the main thread when you call them from another thread. Data that the server already has needs a server-side deletion.

flushBatchRequests() erases nothing. It asks the SDK to send the queued events now and returns at once. Before a start succeeds, and between stop() and the next successful start, it sends nothing.

import InsightSDK

// Screen recordings only: the stored recordings, their queue and any upload in progress
Insight.shared.clearScreenRecordings()

// Crash reports and screen recordings
Insight.shared.clearStoredData()

Network performance tracking

Insight iOS SDK tracks the performance of the HTTP requests that your app makes with URLSession. You can monitor API response times and status codes.

URLSession integration

You write no code. The SDK tracks requests while your server settings turn network performance tracking on. It measures the requests that your app starts with these URLSession methods:

  • dataTask(with:) and dataTask(with:completionHandler:), with a URLRequest or a URL
  • uploadTask(with:from:completionHandler:)
  • downloadTask(with:completionHandler:), with a URLRequest

The SDK adds its measurement to these methods at run time, through method swizzling. It measures requests on URLSession.shared and on every session that your app or a library creates. Your session delegate still gets each call. After stop(), the SDK measures nothing until the next start.

What gets tracked

The network performance tracking captures:

  • Request URL and method (GET, POST, etc.)
  • Response time (total duration from request start to completion)
  • HTTP status codes (200, 404, 500, etc.)
  • Request and response sizes

The SDK removes the user name, password, query and fragment from each URL. For a download task, the response size is 0. The SDK records a request only when it gets an HTTP response, so a request that fails with no response leaves no record.

Which hosts get measured

The Insight platform settings can name the hosts to measure. When they name any, the SDK measures requests to those hosts alone and skips the rest. When they name none, the SDK measures requests to every host. In both cases, the SDK skips the Insight host that it sends its own data to. It also skips every URL whose scheme is not http or https.

Note: The SDK sends each measurement to the Insight platform.

Screen recording (preview)

Preview: Screen recording is in preview. Its behavior can change in a later release.

Overview

Screen recording captures masked frames of your app's screens, so your team can replay a user session. It runs on iOS 15 or later, in UIKit and SwiftUI apps. A frame costs about 70 ms of main-thread time on an iPhone 15 Pro Max. The SDK limits that work to 100 ms in each second.

Screen recording is off until your app's server settings turn it on. The same settings control the privacy level and the frame quality. Your app has nothing to configure, and the SDK has no local switch. When the settings turn recording on, the SDK starts to record at once. Some other changes to the server settings apply at the next app launch.

What you need to do

In most apps, you do not need to write code. The SDK captures a new screen when a view controller appears, a presentation closes, or the key window changes. In SwiftUI, it also captures one when a NavigationStack pushes or pops, a TabView changes tab, or a sheet or cover appears.

Some changes give the SDK no signal. An example is SwiftUI content that your app swaps on state, with an if or a switch in a view body. The SDK then records the new content on its normal schedule, at most once per second by default. A screen that the user leaves within that second can have no frame.

To record a new screen at once, log a screen view event when it appears. The SDK treats the next frame as a new screen and records it outside the once-per-second limit:

import InsightSDK

.onAppear {
    Insight.shared.logEvent(InsightEventOtherScreenView(screenClass: "Checkout", screenName: "Checkout"))
}

To record a change inside one screen, such as a view that your app swaps on a state change, call requestScreenRecordingCapture():

import InsightSDK

Insight.shared.requestScreenRecordingCapture()

The SDK captures the screen at once. The normal capture limits and privacy rules still apply. A call before start, while the SDK is stopped, or while the app is in the background does nothing.

API reference

The table lists every public screen recording API:

API Use it to Notes
var screenRecordingMask: Bool Mask a UIKit view and its subviews. A property on UIView, also in Objective-C. The default is false. The SDK also withholds taps on the view.
var screenRecordingUnmask: Bool Show the text and images of a UIKit view and its subviews. A property on UIView, also in Objective-C. The default is false. It never unmasks always-masked content.
screen-recording-mask in accessibilityIdentifier Mask a UIKit view through its identifier. The identifier can hold other text too. It works as screenRecordingMask does.
screen-recording-unmask in accessibilityIdentifier Unmask a UIKit view through its identifier. The identifier can hold other text too. It works as screenRecordingUnmask does.
func screenRecordingMask() -> some View Mask a SwiftUI view and its children. A SwiftUI modifier. The SDK also withholds taps on the view.
func screenRecordingUnmask() -> some View Show the text and images of a SwiftUI view and its children. A SwiftUI modifier. It never unmasks always-masked content.
func requestScreenRecordingCapture() Capture the screen after a change that the SDK cannot see. Call it on Insight.shared from any thread. It returns at once.
func clearScreenRecordings() Delete every screen recording that the device stores. Call it on Insight.shared from any thread. It also stops an upload in progress, and it works before start.
func clearStoredData() Delete the SDK's stored user data on the device. It deletes every stored recording and the pending crash reports. Data that the server already has needs a server-side deletion.
InsightEventOtherScreenView(screenClass: String, screenName: String, parameters: [String: Value] = [:]) Mark a new screen that the SDK cannot see. Log it with Insight.shared.logEvent(_:callback:). The recording does not show screenName, but a server rule for named screens matches it.

Note: clearScreenRecordings() and clearStoredData() wait for the main thread when you call them from another thread.

Use the screenRecordingMask or screenRecordingUnmask property to mark a UIKit view. For example:

import InsightSDK

cardNumberField.screenRecordingMask = true
headlineLabel.screenRecordingUnmask = true

You can also set the property from Objective-C: self.cardNumberField.screenRecordingMask = YES;.

Put a mask token in the accessibilityIdentifier to mark a view without the property. The sample uses the identifier checkout.card:

cardNumberField.accessibilityIdentifier = "checkout.card screen-recording-mask"

Use the screenRecordingMask() and screenRecordingUnmask() modifiers to mark a SwiftUI view. For example:

import InsightSDK

Text(cardNumber).screenRecordingMask()
Text(headline).screenRecordingUnmask()

The SDK masks the card number and shows the headline in each frame.

Masking

By default, the SDK records text and images as drawn. If the server sets a stricter privacy level, the SDK masks more.

The SDK always masks the following content, whatever the server sends. No mark or rule can unmask it:

  • Secure text entry fields
  • Inputs whose textContentType names a password, a one-time code, a card, a phone number, an e-mail address, a name, an address, or a birthdate
  • WKWebView
  • Video, camera, Metal, and OpenGL layers
  • MKMapView
  • PencilKit canvases
  • Content that another process draws
  • Custom views that the SDK does not recognize, such as a UIView that paints itself in draw(_:)

A scan for personal data (PII) also masks e-mail addresses, card numbers, and similar data in UIKit text that the SDK records in clear.

To keep other content out of a recording, mask it with a property, an identifier token, or a modifier. To show text and images that the privacy level masks, unmask the view. Three rules decide when marks and server rules meet:

  • An unmask in code on a view beats a server rule that masks the same view.
  • A mask wins when a view matches both a mask and an unmask.
  • A mask covers the whole subtree. An unmask inside a masked view does not unmask its content.

The server can also mask or unmask by class name or by rule. A rule matches a UIKit view by its accessibilityIdentifier, its accessibilityLabel, its text, or its kind of view. A rule can apply on every screen or on named screens only. A screen name is the screenName of the latest InsightEventOtherScreenView that your app logged. Without one, it is the class name of the top view controller. Your app does not set class lists or rules. Ask for them in your app's server-side settings.

Give each class as its runtime class name. The SDK matches the name exactly:

  • A Swift class has its module name: MyApp.BalanceLabel.
  • An Objective-C or UIKit class has no prefix: UILabel.
  • The SDK does no substring match, so Label matches no class.
  • In an entry with *, the * stands for any run of characters. For example, MyApp.Wallet* matches every class whose name starts that way.
  • A match includes the subclasses of the class.
  • The SDK ignores an exact name that matches no class. To check a rule, look at a recording.

Class names and server rules reach UIKit views only. A UIKit view that you host with UIViewRepresentable is still a UIKit view. For an element inside SwiftUI, use screenRecordingMask() and screenRecordingUnmask().

Touches

The SDK withholds a tap when it lands on one of the following:

  • A secure or sensitive input
  • A web view
  • A video, camera, or GPU-backed view
  • A map
  • A PencilKit canvas
  • An element that your app masks with the property, the identifier token, or the modifier

A withheld tap leaves no coordinates in the recording, and the SDK drops the whole gesture. The SDK records taps on other masked content. That includes content that only the privacy level, a server rule, or the scan for personal data masks, and unrecognized custom views. To withhold taps on such content, mark it in your code. Two cases need a mark:

  • A signature pad that your app draws itself, in draw(_:) or as a SwiftUI Canvas. The SDK masks its pixels but records its taps, so a viewer can replay the stroke. Mark the pad. PKCanvasView withholds its taps without a mark.
  • A video or GPU layer (AVPlayerLayer, CAMetalLayer) that you add to an ordinary view. The SDK hides the layer in the frame but records a tap on it. Mark the view that holds the layer.

In a UIKit screen, the SDK asks only the topmost drawn view under the finger. A view drawn over a marked view, clear or not, takes the tap back. In a SwiftUI screen, the SDK asks every drawn element under the finger, so a clear overlay does not take the tap. If the server turns touch recording off, the SDK records no touches.

Known limits

  • The SDK does not scan SwiftUI Text for personal data. A card number in a Text shows in the frame. Mark such text with screenRecordingMask().
  • A mark covers the element's layout frame. A child that you move out with .offset shows where it draws. Mark that child too.
  • A mark applied after a rotation covers the unrotated frame, so the ends of the content show. Apply the mark before the transform: Text(cardNumber).screenRecordingMask().rotationEffect(.degrees(20)).
  • When the server masks images, every SwiftUI image, SF Symbol, and shape hides. No workaround exists.
  • The SDK always hides a SwiftUI Canvas, content under .drawingGroup(), and charts drawn the same way. screenRecordingUnmask() does not show them. No workaround exists.
  • A plain text field hides what the user typed at the default text level. No workaround exists.
  • The selection of a menu-style Picker shows when the server masks input text. Mark the picker with screenRecordingMask().
  • On iOS 26, screenRecordingUnmask() also shows text from an overlapping sibling whose center falls inside the element. Keep unmasked elements off secret text, or mark the secret text.
  • The SDK does not record a window of your own that is not the key window, such as a toast window. No workaround exists.
  • In SwiftUI, every destination of one NavigationStack shares one screen name in the recording, and so does every tab of one TabView. No workaround exists.

5. Deprecations

Due to Apple's ongoing privacy enhancements, several features have been deprecated or require special permissions:

IDFA

Since iOS 14, Apple has introduced new privacy features that require user permission to access the IDFA. You'll need to request permission from the user before you can access the identifier.

Here's how to do that:

  • Add the AppTrackingTransparency framework to your project and import it, together with AdSupport for the identifier:
import AppTrackingTransparency
import AdSupport
  • Request permission from the user:
ATTrackingManager.requestTrackingAuthorization { status in
    switch status {
    case .authorized:
        // Tracking authorization dialog was shown
        // and we are authorized
        debugPrint("Authorized")

        // Now that we are authorized we can get the IDFA
        let idfa = ASIdentifierManager.shared().advertisingIdentifier.uuidString
        debugPrint("IDFA: \(idfa)")
    case .denied:
        // Tracking authorization dialog was
        // shown and permission is denied
        debugPrint("Denied")
    case .notDetermined:
        // Tracking authorization dialog has not been shown
        debugPrint("Not Determined")
    case .restricted:
        // Tracking is restricted by some policy
        debugPrint("Restricted")
    @unknown default:
        debugPrint("Unknown")
    }
}
  • Add the NSUserTrackingUsageDescription key to your Info.plist file. This is the message that will be shown to the user when requesting IDFA access permission:
<key>NSUserTrackingUsageDescription</key>
<string>This identifier will be used to deliver personalized ads to you.</string>

Remember that users can choose to deny this permission, in which case you won't be able to access their IDFA.

Insight SDK doesn't immediately collect the IDFA when initialized. It waits for ATT permission to be granted. On the next start of the SDK, it will collect this information if the user has granted the permission.

Device name

Starting with iOS 16, Apple restricted access to the user-defined device name for privacy reasons. This was done to prevent apps from potentially identifying users or devices without explicit permission.

For apps that genuinely need access to the device name (like device management or networking apps), Apple provides an entitlement called Access device name (com.apple.developer.device-information.user-assigned-device-name). However, this entitlement requires approval from Apple, and you need to justify why your app needs this information. If you don't have this entitlement, your app will only get generic device names like "iPhone" or "iPad".

Reference contains relevant information from Apple.

If you have acquired permissions, Insight SDK will collect this information.

Carrier info

Starting iOS 16, carrier name and code information are deprecated. Reference 1 and Reference 2 contains relevant information from Apple.

6. Troubleshooting

Common issues

SDK not starting:

  • Verify API key is correct
  • Check that the device can connect to the API endpoint

Location not working:

  • Verify location permissions in Info.plist
  • Check that user has granted location permission
  • For background location, ensure "Always" permission is granted

Not reporting events in a SwiftUI app:

  • Make sure you've created AppDelegate.swift
  • Verify @UIApplicationDelegateAdaptor is properly configured
  • Check that SDK initialization code is in didFinishLaunchingWithOptions

7. Changelog

  • 1.0.0 (Released 2026-05-06)
    • Initial release
S
Description
No description provided
Readme 18 MiB
Languages
Objective-C 98.8%
Ruby 0.6%
Swift 0.5%
C 0.1%