Perform a Deeplink from Swiftui Widget on Tap

Perform a deeplink from SwiftUI widget on tap

  1. In the Widget view you need to create a Link and set its destination url:
struct SimpleWidgetEntryView: View {
var entry: SimpleProvider.Entry

var body: some View {
Link(destination: URL(string: "widget://link1")!) {
Text("Link 1")
}
}
}

Note that Link works in medium and large Widgets only. If you use a small Widget you need to use:

.widgetURL(URL(string: "widget://link0")!)

  1. In your App view receive the url using onOpenURL:
@main
struct WidgetTestApp: App {
var body: some Scene {
WindowGroup {
Text("Test")
.onOpenURL { url in
print("Received deep link: \(url)")
}
}
}
}

It is also possible to receive deep links in the SceneDelegate by overriding:

func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>)

You can find more explanation on how to use this function in this thread:

  • Detect app launch from WidgetKit widget extension

Here is a GitHub repository with different Widget examples including the DeepLink Widget.

How to perform deeplink from widget to parent app in Objective C

Which method in AppDelegate I will get the callback?

You can use application:openURL:options:

- (BOOL)application:(UIApplication *)app 
openURL:(NSURL *)url
options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options;

SwiftUI small widget is not opening the iOS app on tap

I don’t know why the app doesn’t open (an iOS bug, I guess), but your deeplink won’t work because Link isn’t available in the “small” widget size. You need to set the .widgetURL() modifier on your view instead.

How to use Link in WidgetKit to define arbitrary regions, not just text links?

The type definition of Link is actually struct Link<Label> where Label : View so the only constraint to Label is that it conforms to the View protocol (despite the name indicating otherwise). My preferred initializer is init(destination:, label:) so you can embed every view in the view builder like this:

Link(destination: URL(string: "some://dest")!) {
HStack {
Text("I'm part of the tappable area")
Text("Me too")
}
}

You can actually see this in action in the Emoji Rangers project from Apple (check AllCharactersView.swift.

Detect app launch from WidgetKit widget extension

To detect an app launch from a WidgetKit widget extension where the parent application supports scenes you'll need to implement scene(_:openURLContexts:), for launching from a background state, and scene(_:willConnectTo:options:), for launching from a cold state, in your parent application's SceneDelegate. Also, add widgetURL(_:) to your widget's view.

Widget's View:

struct WidgetEntryView: View {

var entry: SimpleEntry

private static let deeplinkURL: URL = URL(string: "widget-deeplink://")!

var body: some View {
Text(entry.date, style: .time)
.widgetURL(WidgetEntryView.deeplinkURL)
}

}

Parent application's SceneDelegate:

// App launched
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let _: UIWindowScene = scene as? UIWindowScene else { return }
maybeOpenedFromWidget(urlContexts: connectionOptions.urlContexts)
}

// App opened from background
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
maybeOpenedFromWidget(urlContexts: URLContexts)
}

private func maybeOpenedFromWidget(urlContexts: Set<UIOpenURLContext>) {
guard let _: UIOpenURLContext = urlContexts.first(where: { $0.url.scheme == "widget-deeplink" }) else { return }
print(" Launched from widget")
}

How Can I Handle Tap Gesture on Widget?

Okay I created a new project with SwiftUI Environments (not old way AppDelegate and SceneDelegate).

Then I use Link for tap actions and I got it with .onOpenURL modifier in ContentView. It works :)

ContentView:

import SwiftUI

enum SelectedTab: Hashable {
case home
case standings
case options
}

struct ContentView: View {

@State var selectedTab: SelectedTab = .home

var body: some View {
TabView(selection: self.$selectedTab) {
Text("Home")
.tabItem {
Image(systemName: "house")
.renderingMode(.template)
Text("Home")
}.tag(SelectedTab.home)
Text("Standings")
.tabItem {
Image(systemName: "list.number")
.renderingMode(.template)
Text("Standings")
}.tag(SelectedTab.standings)
Text("Options")
.tabItem {
Image(systemName: "gear")
.renderingMode(.template)
Text("Options")
}.tag(SelectedTab.options)
.onOpenURL { (url) in
if url.absoluteString == "widget-deeplink://standings"{
self.selectedTab = .standings
}
}
}
}
}

Link usage example in Widget:

Link(destination: URL(string: "widget-deeplink://standings")!) {
Text("Link Test")
}


Related Topics



Leave a reply



Submit