LimeLink iOS SDK 1.0.0
iOS 12.0+ · Swift 5.0 · Xcode 14.0+
LimeLink iOS SDK handles direct links, Universal Links, deferred deep links, and explicit view tracking through a binary XCFramework. Version 1.0.0 is a breaking release with one incoming-link entry point and one result model.
View previous iOS SDK releases
Release availability
Swift Package Manager 1.0.0 is publicly available from the LimeLink binary repository. Use Swift Package Manager while CocoaPods 1.0.0 completes deployment; select CocoaPods after the CDN resolves it publicly.
Before you start
- Register the iOS Application in a LimeLink Project.
- Copy the canonical Project UUID, a public resource identifier suitable for app configuration.
- Configure Associated Domains and any app-owned callback schemes.
- Define an exact allowlist of destination schemes and HTTPS hosts.
Install
Swift Package Manager
dependencies: [
.package(
url: "https://github.com/hellovelop/limelink-ios-sdk-binary.git",
from: "1.0.0"
)
]
Add the LimelinkIOSSDK product to the app target.
CocoaPods deployment status
After CocoaPods 1.0.0 becomes publicly resolvable, use:
source 'https://cdn.cocoapods.org/'
platform :ios, '12.0'
pod 'LimelinkIOSSDK', '~> 1.0.0'
Do not use Git, path, source, or local-podspec fallback as a production installation route.
Initialize
Register a strongly retained listener early, then initialize once during launch:
import LimelinkIOSSDK
// Retain and register the listener before initialization starts Deferred lookup.
_ = DeepLinkManager.shared
let config = LimeLinkConfig(
projectId: "550e8400-e29b-41d4-a716-446655440000",
loggingEnabled: false
)
LimeLinkSDK.initialize(config: config)
Automatic deferred lookup runs for every eligible installation.
Forward incoming links
Forward Universal Links through the source-neutral API:
func application(
_ application: UIApplication,
continue userActivity: NSUserActivity,
restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void
) -> Bool {
guard userActivity.activityType == NSUserActivityTypeBrowsingWeb,
let url = userActivity.webpageURL else { return false }
LimeLinkSDK.shared.handleIncomingLink(url)
return true
}
For scenes, forward cold URLs from scene(_:willConnectTo:options:) and warm URLs from scene(_:continue:). Registered app-owned custom schemes can also enter handleIncomingLink(_:); the app remains responsible for deciding which lifecycle paths it forwards.
Pre-initialization links use a process-memory capacity-10 FIFO. Direct and Universal duplicates with the same source and exact inbound URL are suppressed while pending/in flight and for five seconds after success. Processing is independent, so callback order can differ from ingress order.
Receive results
final class DeepLinkManager: NSObject, LimeLinkListener {
static let shared = DeepLinkManager()
private override init() {
super.init()
LimeLinkSDK.shared.addLinkListener(self)
}
func onDeeplinkReceived(result: LimeLinkResult) {
guard isAllowedDestination(result.deeplinkUrl) else { return }
navigateTo(result.deeplinkUrl)
}
func onDeferredDeepLinkNotFound() {
// Normal live-only no-match outcome.
}
func onDeeplinkError(error: LimeLinkError) {
showSafeFallback(error.code, error.message)
}
}
LimeLinkResult contains:
| Field | Contract |
|---|---|
deeplinkUrl | Required final URL and sole routing authority |
source | directDeepLink, universalLink, or deferredDeepLink |
originalUrl | Nullable original inbound/server URL |
isDeferred | true only for Deferred results |
All public callbacks run on the main thread. Successful results completed without a listener use a capacity-10, drop-oldest, process-memory FIFO and replay once to the first later listener. Errors and deferred not-found outcomes are live-only.
Always parse deeplinkUrl and exactly compare its scheme and host with an app-owned allowlist before navigation. The host app authorizes the final destination.
Manual deferred handling
LimeLinkSDK.shared.handleDeferredDeepLink { result, error in
if let result {
guard isAllowedDestination(result.deeplinkUrl) else { return }
navigateTo(result.deeplinkUrl)
} else if let error {
showSafeFallback(error.code, error.message)
} else {
// Normal not-found result.
}
}
Matched, not-found, and failed outcomes reach both the completion and current listener exactly once; their relative order is unspecified. Choose one channel as navigation owner.
Explicit stats
Dynamic Lookup already owns lookup attribution. Use trackLinkStatus(url:) only for a separate app-owned view event; it is best effort and should not duplicate a Universal Link event.
Privacy
The XCFramework includes an SDK-owned privacy manifest in every slice. The app remains responsible for its own required-reason APIs, data practices, third-party disclosures, and final merged privacy report.
Migrating from 0.4.1
- Replace removed
handleUniversalLink(_:)withhandleIncomingLink(_:). - Replace
resolvedUriwith requireddeeplinkUrl. - Remove
queryParamsandpathParams; parsedeeplinkUrlin the app when needed. - Use
sourceandoriginalUrlfor source-aware behavior. - Expect native capacity-10 success replay and exact-URL five-second deduplication.
- Keep automatic deferred lookup enabled and choose one completion/listener navigation owner.