Install (CocoaPods)
Add the dependency to your Podfile and open the workspace.
platform :ios, '13.0'
use_frameworks!
target 'YourApp' do
pod 'SDDLSDK', '~> X.Y.Z' # replace with the latest release version
end
# Then:
$ pod install
# Open the generated .xcworkspace
Universal Links (Associated Domains)
- In Xcode: Target → Signing & Capabilities → + Capability → Associated Domains.
- Add your domain line:
applinks:{YOUR_ID}.sddl.me # or your verified custom domain applinks:{your.custom.domain} - Build & run on device and confirm there are no entitlement warnings.
- Make sure your
apple-app-site-associationis reachable (no redirects) athttps://<domain>/.well-known/apple-app-site-association.
Usage — SwiftUI
Handle: direct Universal Link, NSUserActivity, and app launch without a URL (cold start).
import SwiftUI
import SDDLSDK
struct ContentView: View {
var body: some View {
Color.clear
// 1) Universal Link delivered directly
.onOpenURL { url in
SDDLHelper.resolve(url,
onSuccess: handlePayload(_:),
onError: handleError(_:))
}
// 2) Universal Link via NSUserActivity
.onContinueUserActivity(NSUserActivityTypeBrowsingWeb) { activity in
SDDLHelper.resolve(activity.webpageURL,
onSuccess: handlePayload(_:),
onError: handleError(_:))
}
// 3) Cold start (no URL at launch)
.onAppear {
SDDLHelper.resolve(nil,
onSuccess: handlePayload(_:),
onError: handleError(_:),
readClipboard: false)
}
}
}
private func handlePayload(_ payload: [String: Any]) {
// Navigate to the correct screen using payload values
}
private func handleError(_ error: String) {
// Optional: log or show a non-blocking message
}
Usage — UIKit
Forward the received URL/activity and call once on activation to handle cold start.
// SceneDelegate.swift
func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
if userActivity.activityType == NSUserActivityTypeBrowsingWeb,
let url = userActivity.webpageURL {
SDDLHelper.resolve(url,
onSuccess: { payload in /* route */ },
onError: { err in /* handle */ })
}
}
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
if let url = URLContexts.first?.url {
SDDLHelper.resolve(url,
onSuccess: { payload in /* route */ },
onError: { err in /* handle */ })
}
}
// Cold start (no URL yet)
func sceneDidBecomeActive(_ scene: UIScene) {
SDDLHelper.resolve(nil,
onSuccess: { payload in /* route */ },
onError: { err in /* handle */ })
}
Testing & QA
- Domains: use
{YOUR_ID}.sddl.meor your verified custom domain in Associated Domains. - AASA: must be served without redirects at
/.well-known/apple-app-site-association. - Reinstall: after entitlement changes, delete and reinstall the app to refresh Universal Links.
- TestFlight: fine for testing; for more reliable cold start with ad traffic, consider an intermediate page (“web clip” flow).
- Tools: try our Universal Links Validator.
- More: QA Playbook • Deferred deep links guide
Troubleshooting
- Module not found: open the
.xcworkspaceand runpod install. - Universal Link not opening the app: re-check Associated Domains, AASA reachability, and ensure no HTTP→HTTPS redirects on AASA.
- Cold start didn’t navigate: ensure the launch handler is in place (SwiftUI
.onAppearor UIKitsceneDidBecomeActive).
FAQ
Do I need a custom URL scheme?
No. Universal Links are recommended. A custom scheme is optional if you also support myapp:// for internal flows.
Can I use TestFlight?
Yes. It’s OK for validation. For ad traffic and “cold start” reliability, consider enabling an intermediate page before the App Store.