在点击SwiftUI小部件时执行深度链接

21

我有一个简单的中等大小组件,其中包含两个文本。我想要的是能够执行深度链接,将用户引导到我的应用程序的特定部分,但我似乎找不到方法。

我编写的视图(非常简单):

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

我已经尝试替换

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

但这也不起作用。

3个回答

51
  1. 小部件视图中,您需要创建一个链接并设置其目标网址:
struct SimpleWidgetEntryView: View {
    var entry: SimpleProvider.Entry

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

请注意,Link 仅适用于 中型大型 小部件。如果您使用的是 小型 小部件,则需使用以下内容:

.widgetURL(URL(string: "widget://link0")!)
  1. 在您的应用视图中,使用onOpenURL接收URL:
@main
struct WidgetTestApp: App {
    var body: some Scene {
        WindowGroup {
            Text("Test")
                .onOpenURL { url in
                    print("Received deep link: \(url)")
                }
        }
    }
}

SceneDelegate中重写以下方法,也可以接收到深度链接:

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

您可以在此帖子中找到有关如何使用此功能的更多解释:


这是一个GitHub代码库,其中包括深链接小部件在内的不同小部件示例。


链接 .widgetUrl 是如何指定的?如何为应用程序中的特定位置定义此 URL?如果我错了,请纠正我,但我认为 URL 的第一部分显示在应用程序信息部分中指定的 URL 方案,但我无法弄清楚 URL 的第二部分是什么? - Krits
@Krits:小部件中的每个网址都将在应用程序中打开。 因此,scheme可以区分小部件url和其他url(例如来自用户通知的url)。 其他路径组件可以指定操作/位置-由您决定。 您只需要在特定视图中使用onOpenURL(url :),并检查特定的URL是否到达即可。 - pawello2222
正如上面的问题所提到的,“widget://link0”。link0和link1究竟是什么?我们如何在此URL中指定操作和/或位置? - Krits
@Krits 这只是描述操作的自定义文本。在 onOpenURL(url:) 中,您只需检查到达的 URL(如果是 link0 或 link1 ...),然后执行一些操作(显示警报,激活导航链接...)。 - pawello2222
你好,能否请您指明我应该在哪里放置onOpenUrl(url:)函数,因为我是使用Storyboard创建我的应用程序的。 - Krits
1
优美而完整的答案 - Mona

12

此外,如果你没有使用SceneDelegate,你也可以使用AppDelegate来完成这个操作:

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

// OR

Link(destination: URL(string: "urlsceheme://foobarmessage")!) {
    Text("Foo")
}
AppDelegate中设置此代码。
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
   let message = url.host?.removingPercentEncoding // foobarmessage
   return true
}

使用上述代码,我在AppDelegate中没有收到任何消息,请问有什么建议可以交叉检查设置吗? - Hardik Thakkar

4
查看文档上的内容: 响应用户交互 当用户与您的小部件进行交互时,系统会启动您的应用程序来处理请求。当系统激活您的应用程序时,导航到与小部件内容相对应的详细信息。您的小部件可以指定一个URL来通知应用程序显示什么内容。要在您的小部件中配置自定义URL:
  • 对于所有小部件,在小部件的视图层次结构中的一个视图中添加widgetURL(_:)视图修饰符。如果小部件的视图层次结构包含多个widgetURL修饰符,则行为是未定义的
  • 对于使用WidgetFamily.systemMediumWidgetFamily.systemLarge的小部件,在小部件的视图层次结构中添加一个或多个链接控件。您可以同时使用widgetURLLink控件。如果交互目标是一个Link控件,则系统使用该控件中的URL。对于小部件中的其他任何位置的交互,系统将使用widgetURL视图修饰符中指定的URL
例如,一个在游戏中显示单个角色详细信息的小部件可以使用widgetURL打开应用程序以查看该角色的详细信息。
@ViewBuilder
var body: some View {
    ZStack {
        AvatarView(entry.character)
            .widgetURL(entry.character.url)
            .foregroundColor(.white)
    }
    .background(Color.gameBackground)
}

如果小部件显示一个字符列表,列表中的每个项目都可以使用控件。每个Link控件指定了它所显示的特定字符的URL。
当小部件接收到交互时,系统会激活包含的应用程序并将URL传递给onOpenURL(perform:)、application(_:open:options:)或application(_:open:),具体取决于您的应用程序使用的生命周期。
如果小部件不使用widgetURL或Link控件,系统会激活包含的应用程序并将一个NSUserActivity传递给onContinueUserActivity(_:perform:)、application(_:continue:restorationHandler:)或application(_:continue:restorationHandler:)。用户活动的userInfo字典包含有关用户与小部件交互的详细信息。使用WidgetCenter.UserInfoKey中的键从Swift代码中访问这些值。要从Objective-C中访问userInfo值,请改用键WGWidgetUserInfoKeyKind和WGWidgetUserInfoKeyFamily。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接