Perform a deeplink from SwiftUI widget on tap

Viewed 9868

I have a simple widget (medium-sized) with two texts, and what I want is to be able to perform a deep link to lead the user to a specific section of my app, but I can't seem to find a way to do so.

The view I have written (which is very simple):

HStack {
    Text("FIRST ITEM")    
    Spacer()
    Text("SECOND ITEM")
}

I have already tried to replace

Text("SECOND ITEM")

with

Link("SECOND ITEM destination: URL(string: myDeeplinkUrl)!)

but it doesn't work either.

3 Answers
  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:


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

Also, you can do it using AppDelegate (if you not using SceneDelegate):

.widgetURL(URL(string: "urlsceheme://foobarmessage"))

// OR

Link(destination: URL(string: "urlsceheme://foobarmessage")!) {
    Text("Foo")
}

Set this code within AppDelegate

func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
   let message = url.host?.removingPercentEncoding // foobarmessage
   return true
}

See docs on: Respond to User Interactions

When users interact with your widget, the system launches your app to handle the request. When the system activates your app, navigate to the details that correspond to the widget’s content. Your widget can specify a URL to inform the app what content to display. To configure custom URLs in your widget:

  • For all widgets, add the widgetURL(_:) view modifier to a view in your widget’s view hierarchy. If the widget’s view hierarchy includes more than one widgetURL modifier, the behavior is undefined.
  • For widgets that use WidgetFamily.systemMedium or WidgetFamily.systemLarge, add one or more Link controls to your widget’s view hierarchy. You can use both widgetURL and Link controls. If the interaction targets a Link control, the system uses the URL in that control. For interactions anywhere else in the widget, the system uses the URL specified in the widgetURL view modifier.

For example, a widget that displays details of a single character in a game can use widgetURL to open the app to that character’s detail.

@ViewBuilder
var body: some View {
    ZStack {
        AvatarView(entry.character)
            .widgetURL(entry.character.url)
            .foregroundColor(.white)
    }
    .background(Color.gameBackground)
}

If the widget displays a list of characters, each item in the list can be in a Link control. Each Link control specifies the URL for the specific character it displays.

When the widget receives an interaction, the system activates the containing app and passes the URL to onOpenURL(perform:), application(_:open:options:), or application(_:open:), depending on the life cycle your app uses.

If the widget doesn’t use widgetURL or Link controls, the system activates the containing app and passes an NSUserActivity to onContinueUserActivity(_:perform:), application(_:continue:restorationHandler:), or application(_:continue:restorationHandler:). The user activity’s userInfo dictionary contains details about the widget the user interacted with. Use the keys in WidgetCenter.UserInfoKey to access these values from Swift code. To access the userInfo values from Objective-C, use the keys WGWidgetUserInfoKeyKind and WGWidgetUserInfoKeyFamily instead.

Related