【iOS小组件】小组件点击事件和交互

428 阅读2分钟

注意:

  • 针对 iOS 17 及以下系统,小组件和主App交互场景

  • 视图可以设置多个 widgetURL,只有最后一个起作用

与主App交互


  • iOS 17 及以下,点击小组件只能打开主App,通过scheme传参在主App完成交互;

  • iOS 17 及以上,可以直接在小组件上完成点击交互。

组件类型使用限制

  • 对于小型组件(.systemSmall),可以为视图设置 widgetURL(_:)

  • 对于中型组件和大型组件(.systemMedium.systemLarge),不仅可以使用 widgetURL,还可以使用 Link 组件


widgetURL


可以为小组件绑定一个URL,当用户点击这个小组件时,就会调用主App的回调方法,具体调用哪个方法取决于以下条件:

  • 如果你的主App用 SwiftUI,则调用 **onOpenURL(perform:)**方法。

  • 如果你的主App用 SceneDelegate 管理生命周期,则调用 scene(_:, openURLContexts:) 方法。

  • 如果你的主App用 AppDelegate 管理生命周期,则调用 application(_:open:options:) 方法

struct MyWidgetEntryView : View {
    var entry: Provider.Entry

    var body: some View {
        VStack(spacing: 10) {
            Image(systemName: entry.time.icon)
                .imageScale(.large)
                .foregroundColor(.red)
            HStack {
                Text("现在是:")
                Text(entry.time.text)
            }
            .font(.title3)
        }
        .widgetBackground(Color.white)
        .widgetURL(URL(string: "scheme://iosNews.com/p1=1&p2=2"))
    }
}

Link


对于中型组件和大型组件,不仅可以使用 widgetURL,还可以使用 Link 组件。

Link 组件相当于是一个可点击的容器,可以设置一个自定义的 URL:

struct MyWidgetEntryView : View {
    var entry: Provider.Entry

    var body: some View {
        VStack(spacing: 10) {
            HStack(spacing: 10) {
               Link(destination: URL(string: "scheme://url=?www.link1.com")!, label: {
                   Text("链接1").foregroundColor(.blue)
               })
               
               Link(destination: URL(string: "scheme://url=?www.link2.com")!, label: {
                   Text("链接2").foregroundColor(.blue)
               })
               
               Link(destination: URL(string: "scheme://url=?www.link3.com")!, label: {
                   Text("链接3").foregroundColor(.blue)
               })
           }
        }
        .widgetBackground(Color.white)
        .widgetURL(URL(string: "scheme://"))
    }
}

主App拦截处理


小组件的链接点击都会进入到这里,需要在App中区分并做对应处理

import SwiftUI

@main
struct Learn_SwiftUIApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
                .onOpenURL(perform: { url in
                    print("====\(url)")
                })
        }
    }
}

效果


image.png

image.png

本文同步自微信公众号 "程序员小溪" ,这里只是同步,想看及时消息请移步我的公众号,不定时更新我的学习经验。