ios 从WidgetKit小部件扩展检测应用启动

u2nhd7ah  于 12个月前  发布在  iOS
关注(0)|答案(4)|浏览(125)

点击WidgetKit小部件会自动启动其父应用程序。如何检测我的应用程序是否从其WidgetKit小部件扩展启动?
我找不到任何文档在应用程序AppDelegate和/或SceneDelegate中捕获此。

n3schb8v

n3schb8v1#

若要检测从WidgetKit小部件扩展(父应用程序支持场景)启动应用程序,您需要在父应用程序的SceneDelegate中实现scene(_:openURLContexts:)(用于从后台状态启动)和scene(_:willConnectTo:options:)(用于从冷状态启动)。另外,将widgetURL(_:)添加到小部件的视图中。
Widget的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)
    }
    
}

父应用程序的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")
}
q3aa0525

q3aa05252#

SwiftUI 2生命周期

1.将widgetURL添加到您的Widget视图:

struct SimpleWidgetEntryView: View {
    var entry: SimpleProvider.Entry

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

    var body: some View {
        Text("Widget")
            .widgetURL(Self.deeplinkURL)
    }
}

1.检测应用程序是否在onOpenURL中通过深度链接打开:

@main
struct WidgetTestApp: App {
    @State var linkActive = false

    var body: some Scene {
        WindowGroup {
            NavigationView {
                VStack {
                    NavigationLink("", destination: Text("Opened from Widget"), isActive: $linkActive).hidden()
                    Text("Opened from App")
                }
            }
            .onOpenURL { url in
                guard url.scheme == "widget-deeplink" else { return }
                linkActive = true
            }
        }
    }
}

这里是一个GitHub存储库,包含不同的Widget示例,包括DeepLink Widget。

e5nqia27

e5nqia273#

如果您正在为Widget UI设置Widget URL或Link控件,则包含的应用程序将以application(_:open:options:)打开。您可以在URL中设置其他数据以了解来源。
如果您没有使用widgetUrl或链接控件,则包含应用程序将以application(_:continue:restorationHandler:)打开,而userInfo具有WidgetCenter.UserInfoKey。这应该告诉你应用程序从小部件和有关用户的交互信息打开.

djp7away

djp7away4#

我们还可以检测应用程序是从哪个小部件启动的。为每个小部件类型指定一个唯一的URL方案,如下所示:

struct PhotoWidgetExtensionEntryView : View {
var entry: Provider.Entry
private static let smallWidgetDeepLinkURL = URL(string: "small-widget-deeplink://")!
private static let mediumWidgetDeepLinkURL = URL(string: "medium-widget-deeplink://")!
private static let largeWidgetDeepLinkURL = URL(string: "larege-widget-deeplink://")!
@Environment(\.widgetFamily) var widgetFamily
var body: some View {
    switch widgetFamily {
    case .systemSmall:
        Text("Small Widget")
            .widgetURL(Self.smallWidgetDeepLinkURL)
    case .systemMedium:
        IText("Medium Widget")
            .widgetURL(Self.mediumWidgetDeepLinkURL)
    case .systemLarge:
        Text("Large Widget")
            .widgetURL(Self.largeWidgetDeepLinkURL)
    default:
        Text("Large Widget")
            .widgetURL(Self.largeWidgetDeepLinkURL)
      }
   }
}

然后在主应用程序中处理每个方案:

struct WidgetifyApp: App {
@State var linkActive = false
@State var widgetKind = ""
var body: some Scene {
    WindowGroup {
        NavigationStack {
            VStack {
                ContentView().environmentObject(ImageManager())
                    .onOpenURL { url in
                        switch url.scheme {
                        case "small-widget-deeplink":
                            widgetKind = "Small"
                        case "medium-widget-deeplink":
                            widgetKind = "Medium"
                        case "large-widget-deeplink":
                            widgetKind = "Large"
                        default:
                            widgetKind = "Unknown"
                        }
                        linkActive = true
                    }
                    .navigationDestination(isPresented: $linkActive) {
                        Text("Opened from \(widgetKind) Widget")
                    }
              }
          }
       }
    }
}

相关问题