URLSession — Setup¶
Platforms: iOS (iosArm64 + iosSimulatorArm64)
Dependencies¶
Swift Package Manager¶
Add the WiretapKMP SPM package via its GitHub repository URL, then link the WiretapURLSession framework.
- File → Add Package Dependencies…
- Enter the repository URL:
- Set the version rule (e.g. Up to Next Major from
1.0.0-RC2) - Add the
WiretapURLSessionlibrary to your target
Create a Session¶
Use WiretapURLSession in debug builds and plain URLSession in release — zero framework overhead in production:
#if DEBUG
import WiretapURLSession
#endif
class NetworkClient {
#if DEBUG
private let session: WiretapURLSession
init() {
session = WiretapURLSession(configuration: .default) { config in
config.enabled = true
config.shouldLog = { url, method in
KotlinBoolean(value: url.contains("/api/"))
}
config.headerAction = { key in
if key.caseInsensitiveCompare("Authorization") == .orderedSame {
return HeaderActionMask(mask: "***")
}
if key.caseInsensitiveCompare("Cookie") == .orderedSame {
return HeaderActionSkip.shared
}
return HeaderActionKeep.shared
}
config.logRetention = LogRetentionDays(days: 7)
config.maxContentLength = 100 * 1024
}
}
#else
private let session = URLSession.shared
init() {}
#endif
}
Then bridge the two session types with a pair of private helpers so the rest of your networking code stays #if-free:
private func execute(
_ request: URLRequest,
completion: @escaping (Data?, URLResponse?, Error?) -> Void
) {
#if DEBUG
session.intercept(request: request) { data, response, error in
completion(data as Data?, response, error)
}
#else
session.dataTask(with: request) { data, response, error in
completion(data, response, error)
}.resume()
#endif
}
private func createTask(
_ request: URLRequest,
completion: @escaping (Data?, URLResponse?, Error?) -> Void
) -> URLSessionDataTask {
#if DEBUG
session.dataTask(request: request) { data, response, error in
completion(data as Data?, response, error)
}
#else
session.dataTask(with: request) { data, response, error in
completion(data, response, error)
}
#endif
}
All other methods just call execute() or createTask() — no #if DEBUG needed.
Advanced: Using your own URLSession
If you need a custom URLSession instance (e.g. custom delegate or shared session),
use WiretapURLSessionInterceptor directly:
Enable the Inspector UI¶
@main
struct MyApp: App {
init() {
WiretapLauncher_iosKt.enableLaunchTool()
}
var body: some Scene {
WindowGroup { ContentView() }
}
}
Configuration Reference¶
| Property | Swift Type | Default | Description |
|---|---|---|---|
enabled |
Bool |
true |
Master switch — false disables all logging |
shouldLog |
(String, String) -> KotlinBoolean |
logs all | Filter which requests to capture |
headerAction |
(String) -> HeaderAction |
HeaderActionKeep |
Control how headers are logged |
logRetention |
LogRetention |
LogRetentionForever |
How long to keep log entries |
maxContentLength |
Int32 |
512000 (500 KB) |
Max characters for request/response bodies. 0 disables body logging. |
enabled¶
shouldLog¶
Swift Type Bridging
shouldLog returns KotlinBoolean instead of Swift Bool due to Kotlin/Native interop. Use KotlinBoolean(value: true/false).
headerAction¶
config.headerAction = { key in
if key.caseInsensitiveCompare("Authorization") == .orderedSame {
return HeaderActionMask(mask: "***")
}
if key.caseInsensitiveCompare("Cookie") == .orderedSame {
return HeaderActionSkip.shared
}
return HeaderActionKeep.shared
}
Swift Singletons
HeaderActionKeep and HeaderActionSkip are Kotlin objects — access them via .shared in Swift. HeaderActionMask is a data class and is constructed normally.
logRetention¶
config.logRetention = LogRetentionForever.shared
config.logRetention = LogRetentionAppSession.shared
config.logRetention = LogRetentionDays(days: 7)
maxContentLength¶
Control the maximum number of characters stored for request and response bodies. Bodies exceeding this limit are truncated before being saved to the database. Capped at 500 KB. Set to 0 to skip body logging entirely: