注意:
针对 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)")
})
}
}
}
效果
本文同步自微信公众号 "程序员小溪" ,这里只是同步,想看及时消息请移步我的公众号,不定时更新我的学习经验。