Deep Links
Deep links allow you to bring a user to a particular part of your app. Skip supports custom URL schemes and SwiftUI deep link handling.
Darwin Setup
To support deep links in your iOS build, first follow Apple’s instructions to register your custom URL scheme in Xcode.
Only pay attention to the instructions for registering your custom URL scheme. Ignore the remaining instructions about handling deep links in your code, because you’ll be using SwiftUI’s deep link processing instead.
Android Setup
Edit your Android build’s AndroidManifest.xml
to add an intent-filter
for your custom URL scheme. For example to support myurlscheme
, add the following to your AndroidManifest.xml
:
<manifest ...>
...
<application ...>
...
<activity ...>
...
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="myurlscheme" />
</intent-filter>
</activity>
</application>
</manifest>
While iOS is flexible, Android will expect deep link URLs with the general form scheme://host
or scheme://host/path
.
SwiftUI
SwiftUI uses the onOpenURL
view modifier to intercept and process deep links. Place the modifier on a view that will be rendered when the app opens, and use its action to process the given URL. This will typically involve updating your navigation bindings to take the user to a specified location in the app, as in the following sample:
enum Tab : String {
case cities, favorites, settings
}
public struct ContentView: View {
@AppStorage("tab") var tab = Tab.cities
@State var cityListPath = NavigationPath()
public var body: some View {
TabView(selection: $tab) {
NavigationStack(path: $cityListPath) {
CityListView()
}
...
.tag(Tab.cities)
NavigationStack {
FavoriteCityListView()
}
...
.tag(Tab.favorites)
SettingsView()
...
.tag(Tab.settings)
}
// travel://<tab>[/<city>], e.g. travel://cities/London or travel://favorites
.onOpenURL { url in
if let tabName = url.host(), let tab = Tab(rawValue: tabName) {
self.tab = tab // Select the encoded tab
if tab == .cities, let city = city(forName: url.lastPathComponent)) {
// iOS needs an async dispatch after switching tabs to read navigationDestinations
DispatchQueue.main.async {
// Set nav stack to root + specified city
cityListPath.removeLast(cityListPath.count)
cityListPath.append(city.id)
}
}
}
}
}
}
Testing
On iOS, the easiest way to test your deep link handling is by entering a URL with your custom scheme into Safari. You can also write a URL into a Calendar event or a Note. iOS will linkify the text so that tapping it will open your app.
Android includes an adb
command for sending intents to the running emulator or device, including deep links. Building on our SwiftUI example above, enter a command like the following in Terminal:
% adb shell am start -W -a android.intent.action.VIEW -d "travel://cities/London"