iOS Integration
On this page you'll find integration guides for iOS platforms. Use the tabs to pick your framework.
- Swift
- Objective-C
- React Native
- Expo
- Flutter
Swift Integration
Consent URL: https://consent.example.com/consent?cr_id=...&mobile_app=true&app_scheme=myapp
Basic Implementation
import UIKit
class ConsentViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let button = UIButton(type: .system)
button.setTitle("Open Consent", for: .normal)
button.addTarget(self, action: #selector(openConsent), for: .touchUpInside)
button.frame = CGRect(x: 100, y: 100, width: 200, height: 50)
view.addSubview(button)
}
@objc func openConsent() {
let consentURL = "https://consent.example.com/consent?cr_id=...&mobile_app=true&app_scheme=myapp"
if let url = URL(string: consentURL) {
UIApplication.shared.open(url)
}
}
}
Deep Link Handling
Configure Info.plist:
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string>com.example.myapp</string>
<key>CFBundleURLSchemes</key>
<array>
<string>myapp</string>
</array>
</dict>
</array>
Handle callbacks in AppDelegate.swift:
import UIKit
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool {
if url.scheme == "myapp" && url.host == "consent" {
let components = URLComponents(url: url, resolvingAgainstBaseURL: true)
let status = components?.queryItems?.first(where: { $0.name == "status" })?.value
let receiptId = components?.queryItems?.first(where: { $0.name == "receiptId" })?.value
let crId = components?.queryItems?.first(where: { $0.name == "crId" })?.value
print("Consent completed with status: \(status ?? "unknown")")
if let receiptId = receiptId, let crId = crId {
print("Receipt ID: \(receiptId), CR ID: \(crId)")
}
return true
}
return false
}
}
Objective-C Integration
Consent URL: https://consent.example.com/consent?cr_id=...&mobile_app=true&app_scheme=myapp
Basic Implementation
#import <UIKit/UIKit.h>
@interface ConsentViewController : UIViewController
@end
@implementation ConsentViewController
- (void)viewDidLoad {
[super viewDidLoad];
UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
[button setTitle:@"Open Consent" forState:UIControlStateNormal];
[button addTarget:self action:@selector(openConsent) forControlEvents:UIControlEventTouchUpInside];
button.frame = CGRectMake(100, 100, 200, 50);
[self.view addSubview:button];
}
- (void)openConsent {
NSString *consentURL = @"https://consent.example.com/consent?cr_id=...&mobile_app=true&app_scheme=myapp";
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:consentURL]];
}
@end
Deep Link Handling
Configure Info.plist:
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string>com.example.myapp</string>
<key>CFBundleURLSchemes</key>
<array>
<string>myapp</string>
</array>
</dict>
</array>
Handle callbacks in AppDelegate.m:
#import "AppDelegate.h"
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
if ([url.scheme isEqualToString:@"myapp"] && [url.host isEqualToString:@"consent"]) {
NSURLComponents *components = [NSURLComponents componentsWithURL:url resolvingAgainstBaseURL:YES];
NSString *status = nil;
NSString *receiptId = nil;
NSString *crId = nil;
for (NSURLQueryItem *item in components.queryItems) {
if ([item.name isEqualToString:@"status"]) {
status = item.value;
} else if ([item.name isEqualToString:@"receiptId"]) {
receiptId = item.value;
} else if ([item.name isEqualToString:@"crId"]) {
crId = item.value;
}
}
NSLog(@"Consent completed: %@", status);
NSLog(@"Receipt ID: %@, CR ID: %@", receiptId, crId);
return YES;
}
return NO;
}
@end
React Native Integration
Consent URL: https://consent.example.com/consent?cr_id=...&mobile_app=true&app_scheme=myapp
Basic Implementation
import { Linking, Button, View } from 'react-native';
export default function ConsentScreen() {
const openConsent = () => {
Linking.openURL('https://consent.example.com/consent?cr_id=...&mobile_app=true&app_scheme=myapp').catch(err =>
console.error('Failed to open URL:', err)
);
};
return (
<View>
<Button title="Open Consent" onPress={openConsent} />
</View>
);
}
Deep Link Handling
Configure AndroidManifest.xml:
<activity
android:name=".ConsentActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:scheme="myapp"
android:host="consent"
android:path="/callback" />
</intent-filter>
</activity>
Configure Info.plist:
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string>com.example.myapp</string>
<key>CFBundleURLSchemes</key>
<array>
<string>myapp</string>
</array>
</dict>
</array>
Listen for callbacks:
import { useEffect } from 'react';
import { Linking } from 'react-native';
export default function App() {
useEffect(() => {
const subscription = Linking.addEventListener('url', handleDeepLink);
Linking.getInitialURL().then((url) => {
if (url != null) {
handleDeepLink({ url });
}
});
return () => subscription.remove();
}, []);
const handleDeepLink = ({ url }) => {
if (url.includes('myapp://consent/callback')) {
const params = new URLSearchParams(url.split('?')[1]);
const status = params.get('status');
const receiptId = params.get('receiptId');
const crId = params.get('crId');
console.log('Consent completed:', { status, receiptId, crId });
}
};
}
Expo Integration
Consent URL: https://consent.example.com/consent?cr_id=...&mobile_app=true&app_scheme=myapp
Basic Implementation
import * as Linking from 'expo-linking';
import { Button } from 'react-native';
export default function ConsentScreen() {
return (
<Button
title="Open Consent Window"
onPress={() => Linking.openURL('https://consent.example.com/consent?cr_id=...&mobile_app=true&app_scheme=myapp')}
/>
);
}
Deep Link Handling
Configure in app.json:
{
"expo": {
"scheme": "myapp",
"plugins": [
[
"expo-url-handler",
{
"scheme": "myapp"
}
]
]
}
}
Listen for callbacks:
import { useEffect } from 'react';
import * as Linking from 'expo-linking';
export default function App() {
useEffect(() => {
const subscription = Linking.addEventListener('url', handleDeepLink);
return () => subscription.remove();
}, []);
const handleDeepLink = ({ url }) => {
const route = url.replace(/.*?:\/\//g, '');
if (route.startsWith('consent/callback')) {
const params = new URLSearchParams(route.split('?')[1]);
const status = params.get('status');
const receiptId = params.get('receiptId');
const crId = params.get('crId');
console.log('Consent completed:', { status, receiptId, crId });
}
};
}
Flutter Integration
Consent URL: https://consent.example.com/consent?cr_id=...&mobile_app=true&app_scheme=myapp
Basic Implementation
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';
class ConsentScreen extends StatelessWidget {
void _openConsent() async {
try {
if (await canLaunchUrl(Uri.parse('https://consent.example.com/consent?cr_id=...&mobile_app=true&app_scheme=myapp'))) {
await launchUrl(Uri.parse('https://consent.example.com/consent?cr_id=...&mobile_app=true&app_scheme=myapp'),
mode: LaunchMode.externalApplication);
}
} catch (e) {
print('Error: $e');
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Consent')),
body: Center(
child: ElevatedButton(
onPressed: _openConsent,
child: Text('Open Consent Window'),
),
),
);
}
}
Deep Link Handling
Configure AndroidManifest.xml:
<activity
android:name=".ConsentActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:scheme="myapp"
android:host="consent"
android:path="/callback" />
</intent-filter>
</activity>
Configure Info.plist:
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string>com.example.myapp</string>
<key>CFBundleURLSchemes</key>
<array>
<string>myapp</string>
</array>
</dict>
</array>
Handle callbacks:
import 'package:uni_links/uni_links.dart';
class MyApp extends StatefulWidget {
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
late StreamSubscription deepLinkSubscription;
@override
void initState() {
super.initState();
deepLinkSubscription = uriLinkStream.listen(
(String? link) {
if (link != null && link.contains('myapp://consent/callback')) {
final uri = Uri.parse(link);
final status = uri.queryParameters['status'];
final receiptId = uri.queryParameters['receiptId'];
final crId = uri.queryParameters['crId'];
print('Consent completed: $status');
print('Receipt ID: $receiptId, CR ID: $crId');
}
},
onError: (Object err) {
print('Error: $err');
},
);
}
@override
void dispose() {
deepLinkSubscription.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: ConsentScreen(),
);
}
}