Supported baseline: iOS 13+, Swift tools 5.9. Use the supplied P2PSdk Swift package rather than creating a custom C-to-Swift wrapper.
Add the package
Section titled “Add the package”Your onboarding bundle contains a versioned Swift package reference or a local package directory with the matching P2PSdk.xcframework staged under Artifacts/.
In Xcode:
- Choose File → Add Package Dependencies.
- Select Add Local for an onboarding bundle, or enter the private package URL supplied to your team.
- Add product
P2PSdkto the application target. - Confirm the package links its
CP2PSdkbinary dependency.
Do not drag a native XCFramework into the app and independently copy Swift wrapper source; that can separate wrapper and native versions.
Configure consent
Section titled “Configure consent”Add the values supplied during onboarding to the application Info.plist:
<key>P2PSDKConsentURL</key><string>https://your-onboarding-consent-url.example</string><key>P2PSDKConsentRevokeURL</key><string>https://your-onboarding-revoke-url.example</string><key>P2PSDKConsentVersion</key><string>YOUR_CONSENT_VERSION</string><key>P2PSDKConsentPublicKeyPEM</key><string>-----BEGIN PUBLIC KEY-----YOUR_PUBLIC_KEY-----END PUBLIC KEY-----</string>The public key is safe to ship. Never place a private signing key in the application bundle.
Initialize from a view controller
Section titled “Initialize from a view controller”import P2PSdkimport UIKit
@MainActorfinal class SdkController { private var sdk: P2PSdk?
func start(from presenter: UIViewController, apiKey: String) async { let result = await P2PSdk.createWithConsent( from: presenter, apiKey: apiKey, debug: false, callbackQueue: .main )
guard result.isAccepted, let acceptedSdk = result.sdk else { print("P2PSDK consent result: \(result.status)") return }
acceptedSdk.onConnect = { print("P2PSDK connected") } acceptedSdk.onDisconnect = { reason in print("P2PSDK disconnected: \(reason)") }
do { try acceptedSdk.connect() sdk = acceptedSdk } catch { acceptedSdk.close() print("P2PSDK failed to start: \(error)") } }
func stop() { sdk?.close() sdk = nil }}Call createWithConsent from a visible presenter when a new decision may be required. A successful connect() starts the supervisor; wait for onConnect before displaying online state.
Callback queue and ownership
Section titled “Callback queue and ownership”The Swift wrapper owns the native handle, clears callbacks before native release, and dispatches lifecycle callbacks onto the configured DispatchQueue. Keep the wrapper strongly referenced while participation should continue.
Use disconnect() to pause and close() for terminal release. Releasing the final wrapper reference also ends its native lifetime, but an explicit owner and close path are easier to test.
Revoke consent
Section titled “Revoke consent”func revoke() async { guard let sdk else { return } do { _ = try await sdk.revokeConsent() self.sdk = nil // Successful active-instance revoke closes it. } catch { // Keep the instance so the user can retry. print("P2PSDK revoke failed: \(error)") }}Background limits
Section titled “Background limits”Normal iOS background policy applies. P2PSDK does not declare an execution mode, bypass suspension, or guarantee continuous operation after the app enters background. Test on real devices and align reward messaging with actual eligible participation.
iOS verification
Section titled “iOS verification”- Test a clean install, accept, decline, sheet dismissal, expired/mismatched decision, and revoke.
- Verify connected/disconnected callbacks run on the expected queue.
- Exercise background/foreground transitions, device lock, network changes, low battery, and termination.
- Confirm no callback arrives after
close()and that the XCFramework matches package version1.0.0.