iOS SDK docs

Download the iOS SDK (Swift, iOS 13+, also callable from Objective-C), add it with Swift Package Manager or CocoaPods, initialize and configure it, stay privacy compliant, and learn the auto-collected events and metrics.

Overview

The iOS SDK matches the Android SDK and reports into the same App console, with reports split by platform. It ships as a binary xcframework with KSCrash (crash capture) built in, and automatically collects sessions, screens, launch time, crashes and main-thread hangs.

1
Create an appAdd an app under "My apps" in the console to get its APP_KEY.
2
Add the dependencyAdd FmengSDK with Swift Package Manager or CocoaPods, or download the xcframework.
3
Configure and initializeSet FMENG_APPKEY in Info.plist and call Fmeng.start() at launch.
4
View reportsLaunch the app once; after the install check passes you can see the overview, crashes and launch performance.

Add the dependency

Swift Package Manager is recommended; CocoaPods also works. The SDK is a binary xcframework, so no other dependencies are fetched:

swift
// Package.swift (or Xcode → File → Add Package Dependencies… → http://a.t3j.com/ios-sdk/FmengSDK.git)
dependencies: [
.package(url: "http://a.t3j.com/ios-sdk/FmengSDK.git", from: "1.0.1"),
],
targets: [
.target(name: "MyApp", dependencies: [
.product(name: "FmengSDK", package: "FmengSDK"),
]),
]

In Xcode choose File → Add Package Dependencies…, enter the URL below and use the Up to Next Major Version rule:http://a.t3j.com/ios-sdk/FmengSDK.git

Without a package manager, download the xcframework zip, unzip it into your project and set it to Embed & Sign under Target → General → Frameworks, Libraries, and Embedded Content.

Initialization

Put the App Key and channel in Info.plist (the same keys as FMENG_APPKEY / FMENG_CHANNEL on Android). Find FMENG_APPKEY under "App settings - Basics" in the console. FMENG_CHANNEL is optional; when omitted it is detected automatically: simulator on the simulator, testflight for TestFlight and Xcode installs, appstore for the App Store.

xml
<!-- Info.plist -->
<key>FMENG_APPKEY</key>
<string>APP_KEY</string>
<!-- optional: distribution channel; auto-detected (appstore / testflight / simulator) when omitted -->
<key>FMENG_CHANNEL</key>
<string>appstore</string>

Then call Fmeng.start() as early as possible at launch; crash capture and cold-start timing begin here:

swift
// AppDelegate.swift
import FmengSDK
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// App Key / channel come from Info.plist (FMENG_APPKEY / FMENG_CHANNEL).
Fmeng.start()
return true
}

You can also skip Info.plist and pass the configuration in code (values set in code take precedence):

swift
let config = FmengConfig(appKey: "APP_KEY")
config.channel = "appstore"
config.debug = true // system log, subsystem com.fmeng.analytics
config.hangThreshold = 3 // seconds; default 2
Fmeng.start(config: config)

start does only light work on the main thread (reading the switch, registering lifecycle notifications, installing crash capture); the device ID, device info and offline queue load on the SDK's work queue, so track calls made right after start are neither lost nor reordered.

Options

FmengConfig properties (the App Key and channel can also go in Info.plist; values set in code take precedence):

AttributeDefaultDescription
appKeyRequiredThe APP_KEY generated when the app was created in the console; set it in code or as FMENG_APPKEY in Info.plist.
channelAutoDistribution channel for the "Versions & channels" report; falls back to FMENG_CHANNEL, then to the install source.
regionGlobalCollection node: "cn" reports to the China mainland node (1.1.0+); falls back to FMENG_REGION in Info.plist. Both nodes feed the same console.
debugfalsePrint debug logs (Xcode console / Console.app, subsystem com.fmeng.analytics).
crashReporttrueCapture crashes (NSException, C++ exceptions, Mach exceptions and signals) and send them on the next launch.
hangReporttrueCapture main-thread hangs, shown on the "ANR" page in the console.
hangThreshold2 (s)How long the main thread must be blocked to count as a hang; hangs killed by the system are always reported.
autoTrackScreenstrueRecord a screen view when a UIViewController appears, named after its class; mark SwiftUI screens with .fmengScreen.
sessionTimeout30 (s)Returning to the foreground after this long in the background starts a new launch (session).

API

Custom events, manual screens and signed-in users. Event names are at most 64 characters; up to 30 properties, keys at most 64 characters and string values at most 256; values can be strings, numbers or booleans:

Swift
Fmeng.track("purchase", properties: ["sku": "A100", "price": 199]) // custom event
Fmeng.trackScreen("Cart") // manual screen
Text("Home").fmengScreen("Home") // SwiftUI screen
Fmeng.setUserId("u_123") // after sign-in; nil on sign-out
Fmeng.flush() // send queued events now
Fmeng.setEnabled(false) // stop collecting (e.g. before privacy consent)

All methods are thread-safe; calls before start are no-ops (except setEnabled); internal SDK errors never propagate to the app. With an invalid App Key, start only logs an error and the SDK stays uninitialized.

HTTP collection address

iOS allows only https by default (ATS). If the collection address is http, allow cleartext loads for its domain in Info.plist; skip this step for https addresses.

xml
<!-- Info.plist -->
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>a.t3j.com</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
</dict>
</dict>

Privacy compliance

Turn analytics off until the user accepts your privacy policy. While off, the SDK generates no device ID, reads no device or network info, installs no crash capture and collects no events; the switch is persisted across launches.

swift
if !PrivacyStore.agreed { Fmeng.setEnabled(false) } // must be called before start
Fmeng.start()
// after the user accepts the privacy policy
Fmeng.setEnabled(true) // persisted; enabled on later launches

The SDK ships a privacy manifest, PrivacyInfo.xcprivacy (required by the App Store), declaring the data collected (device ID, user ID, product interaction, crashes, performance, coarse location) and Required Reason APIs (UserDefaults, systemUptime). It is not used for tracking and does not collect the IDFA, so no ATT prompt is needed; tick these types when filling in "App Privacy" in App Store Connect.

Auto-collected events

The SDK collects the following events automatically. Events are stored locally and sent in gzip batches per session, retrying when offline; crashes and hangs are sent on the next launch.

EventFired whenKey fields
launchCold, warm and hot starts (over 60 s discarded)launch_type, duration (ms)
foregroundApp returns to the foregroundSession ID
backgroundApp goes to the background (requests a little background time to finish sending)Foreground duration
screen_viewA UIViewController appears, or trackScreen / .fmengScreenScreen name
crash (native)NSException, C++ exceptions, Mach exceptions and signalsException or signal name, message, stack
crash (anr)Main thread blocked for hangThreshold and then recovered, or killed by the system while hungMain thread stack

Every upload carries the device context: bundle ID, version and build, channel, OS version, model, screen size, locale and network type. The IDFA, IDFV, carrier and location are not collected; location is resolved from the IP on the server, and the visitor IP is stored on the server and only available through the open API (MCP), not shown in the console. The device ID is a random UUID generated by the SDK and changes after reinstall.

Notes

  • Do not test crashes with the Xcode debugger attached: it intercepts crash signals first. Stop the app in Xcode, open it from the home screen, trigger the crash, then reopen the app to send the report.
  • Other crash reporters (Firebase Crashlytics, Bugly, Sentry, etc.) usually coexist, but only one can receive complete Mach exceptions; if you want just one, set crashReport = false and keep hang capture.
  • Only the main app is supported; do not call start in app extensions (widgets, notification extensions, etc.).
  • Crash stacks are symbolicated on device: system library frames have symbol names, while your own code in Release builds shows as image name + offset and needs your app's dSYM to symbolicate; the stack ends with your image UUID and load address.

Metric definitions

iOS and Android share the App Analytics metric definitions (active users, launches, session length, time on screen, retention, etc.); see Metric definitions in the Android SDK docs. Differences on iOS:

  • Crashes include NSException, C++ exceptions, Mach exceptions and signals (including Swift runtime errors such as force-unwrapping nil or index out of range), have type native, and count toward the crash rate together with Android Java + Native crashes; crashes at the same location in the same build are grouped into one issue.
  • iOS has no ANR; main-thread hangs are counted the same way and shown on the "ANR" page in the console, separately from the crash rate.
  • Launch time: cold is process creation to the first frame after first activation; warm is measured from start for iOS 15 prewarmed processes, or the first open after a background launch; hot is returning from the background to the first frame.
  • Sessions: a cold start begins a new session; returning after more than sessionTimeout (30 s by default) in the background also does.
Didn't find an answer?After signing in, check the announcements under the bell at the top right, or find our contact details on the About page.