This guide covers everything you need to update when migrating from the legacy DocV iOS 2.x SDK to the current Trulioo KYC Documents iOS SDK.
Use this guide if your integration uses any of the following :
pod 'TruliooDocV'as your CocoaPods dependencyimport TruliooSDKTruliooDelegatefor lifecycle callbacksTruliooWorkflowto configure the launchTrulioo().initialize(delegate:workflow:)orTrulioo().launch(delegate:)
What's Changed: At a Glance
| Area | 2.x | Current |
|---|---|---|
| Distribution | CocoaPods TruliooDocV) | Swift Package Manager TruliooKYCDocuments) |
| Import | import TruliooSDK | import TruliooKYCDocuments |
| Lifecycle model | Delegate-based TruliooDelegate) | Explicit initialize-then-launch with callbacks |
| Launch configuration | TruliooWorkflow object | Shortcode string only |
| Theme and locale | Set in TruliooWorkflow | Set in backend transaction configuration |
| Initialization | initialize(delegate:workflow:) | initialize(shortcode:completion:) |
| Launch (UIKit) | launch(delegate:) | launchController(callbacks:) |
| Launch (SwiftUI) | Not available | launch(callbacks:) |
| Result model | onComplete, onError, onException | TruliooCallbacks with onComplete and onError |
Before You Start
The 3.x SDK drops CocoaPods entirely in favor of Swift Package Manager. If your project still uses CocoaPods for other dependencies, you can mix SPM and CocoaPods in the same project — but the Trulioo SDK itself must be added through SPM.
Step 1: replace the Dependency
Remove the CocoaPods dependency and add the Swift package instead.
Remove from your Podfile:
pod 'TruliooDocV'Add to your Package.swift :
dependencies: [
.package(url: "https://github.com/Trulioo/kyc-documents.git", from: "X.Y.Z")
]
For beta builds, pin the prerelease tag explicitly:
dependencies: [
.package(url: "https://github.com/Trulioo/kyc-documents.git", exact: "X.Y.Z-beta.N")
]
Link the product to your target:
.target(
name: "YourApp",
dependencies: [
.product(name: "TruliooKYCDocuments", package: "kyc-documents")
]
)
Update your import:
// Before
import TruliooSDK
// After
import TruliooKYCDocumentsStep 2: Remove TruliooDelegate
The delegate-based lifecycle has been removed. Delete your TruliooDelegate conformance and all delegate methods:
// Remove all of this
final class YourViewController: UIViewController, TruliooDelegate {
func onInitialized() { ... }
func onComplete(result: TruliooSuccess) { ... }
func onError(error: TruliooError) { ... }
func onException(exception: TruliooException) { ... }
}Callbacks are now passed directly to launch(callbacks:) or launchController(callbacks:) using TruliooCallbacks. See Step 4.
Step 3: Remove TruliooWorkflow
TruliooWorkflow and TruliooWorkflowTheme have been removed from the public iOS contract. Delete any usage of these in your host app:
// Remove this entirely
let workflow = TruliooWorkflow(
shortcode: shortcode,
locale: "en-US",
isDemoMode: false,
enableRegionSelection: true,
enableDocumentAutoCapture: true,
)
Settings that were previously passed through TruliooWorkflow — locale, theme, region selection, capture behavior — are now resolved from the transaction configuration on your backend. Move these settings to the backend flow that generates the shortcode.
Note on locale: The current SDK resolves locale from device settings or transaction configuration. Remove any host-side locale injection and rely on the current SDK-controlled behavior.
Step 4: Update the Launch Contract
Replace the old delegate-based initialize and launch pattern with the explicit initialize-then-launch flow.
UIKit
// Before
import TruliooSDK
final class YourViewController: UIViewController, TruliooDelegate {
func start(shortcode: String) {
let workflow = TruliooWorkflow(shortcode: shortcode, locale: "en-US")
Trulioo().initialize(delegate: self, workflow: workflow)
}
func onInitialized() {
Trulioo().launch(delegate: self)
}
func onComplete(result: TruliooSuccess) { print(result.transactionId) }
func onError(error: TruliooError) { print(error.message) }
func onException(exception: TruliooException) { print(exception.message) }
}
// After
import TruliooKYCDocuments
final class DocsHostViewController: UIViewController {
private let trulioo = Trulioo()
func start(shortcode: String) {
trulioo.initialize(shortcode: shortcode) { [weak self] result in
guard let self else { return }
guard case .authorized = result else {
print("Initialization failed:", result)
return
}
let controller = self.trulioo.launchController(
callbacks: TruliooCallbacks(
onComplete: { [weak self] _ in
self?.dismiss(animated: true)
self?.trulioo.reset()
},
onError: { [weak self] error in
print("Hosted flow error:", error)
self?.dismiss(animated: true)
self?.trulioo.reset()
}
)
)
self.present(controller, animated: true)
}
}
}SwiftUI
SwiftUI launch is new in 3.x — there was no equivalent in 2.x. Use launch(callbacks:) after initialization returns .authorized
import SwiftUI
import TruliooKYCDocuments
struct HostedDocsView: View {
@State private var trulioo = Trulioo()
@State private var isAuthorized = false
let shortcode: String
var body: some View {
Group {
if isAuthorized {
trulioo.launch(
callbacks: TruliooCallbacks(
onComplete: { _ in
isAuthorized = false
trulioo.reset()
},
onError: { _ in
isAuthorized = false
trulioo.reset()
}
)
)
.ignoresSafeArea()
} else {
Button("Start verification") {
trulioo.initialize(shortcode: shortcode) { result in
if case .authorized = result {
isAuthorized = true
}
}
}
}
}
}
}Step 5: Update Result Handling
Replace the legacy delegate callback methods with TruliooCallbacks
// Before (delegate methods)
func onComplete(result: TruliooSuccess) { ... }
func onError(error: TruliooError) { ... }
func onException(exception: TruliooException) { ... }
// After (TruliooCallbacks)
let callbacks = TruliooCallbacks(
onComplete: { transactionId in
print("Completed:", transactionId ?? "missing")
},
onError: { result in
print("Error:", result)
}
)Key Differences:
onInitialized()is replaced by waiting for.authorized(transactionId:)in the initialization completion.onExceptionhas no direct equivalent — unexpected termination is handled throughonError.- Call
reset()after bothonCompleteandonErrorbefore starting a new transaction.
Current Result Types
| Result | When it is returned |
|---|---|
TruliooResult.authorized(transactionId:) | Initialization succeeded — ready to launch |
TruliooResult.complete(transactionId:) | Hosted flow completed successfully |
TruliooResult.error(message:details:code:transactionId:) | Hosted flow ended with a structured error |
Step 6: Review Host-Side Options (Optional)
The current SDK exposes a much narrower set of host-side options than 2.x. The only public launch option is TruliooLaunchOptions, which lets you skip the intro consent screen:
// UIKit
let controller = trulioo.launchController(
options: TruliooLaunchOptions(skipIntroConsent: true),
callbacks: callbacks
)
// SwiftUI
let view = trulioo.launch(
options: TruliooLaunchOptions(skipIntroConsent: true),
callbacks: callbacks
)This is not a replacement for TruliooWorkflow. All other configuration belongs in the backend transaction.
Migration Checklist
- Remove pod
TruliooDocVfrom your Podfile. - Add the
TruliooKYCDocumentsSwift package from https://github.com/Trulioo/kyc-documents.git. - Replace import
TruliooSDKwith importTruliooKYCDocuments. - Remove
TruliooDelegateconformance and all delegate method implementations. - Delete all
TruliooWorkflowandTruliooWorkflowThemeusage from the host app. - Move theme, locale, demo mode, and region/capture settings to backend transaction configuration.
- Replace
initialize(delegate:workflow:)withinitialize(shortcode:completion:). - Replace
launch(delegate:)withlaunchController(callbacks:)(UIKit) orlaunch(callbacks:)(SwiftUI). - Update result handling to use
TruliooCallbackswithonCompleteandonError. - Call
reset()after bothonCompleteandonErrorbefore starting a new transaction. - Review whether
TruliooLaunchOptions(skipIntroConsent: true)is needed for your flow.

