Обнаружение запуска приложения из расширения виджета WidgetKit

#ios #swift #swiftui #ios14 #widgetkit

#iOS #swift #swiftui #ios14 #widgetkit

Вопрос:

Нажатие на виджет WidgetKit автоматически запускает его родительское приложение. Как я могу определить, было ли мое приложение запущено из расширения виджета WidgetKit?

Я не могу найти какую-либо документацию по записи этого в приложениях AppDelegate и / или SceneDelegate .

Ответ №1:

Чтобы обнаружить запуск приложения из WidgetKit widget extension, где родительское приложение поддерживает сцены, вам необходимо реализовать scene(_:openURLContexts:) для запуска из фонового состояния и scene(_:willConnectTo:options:) для запуска из холодного состояния в SceneDelegate родительском приложении. Кроме того, добавьте widgetURL(_:) в представление вашего виджета.

Виджет 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")
}
  

Комментарии:

1. Почему приложение about apps не поддерживает делегирование сцены? можно ли реализовать из AppDelegate?

2. Я делаю без swift ui, за исключением поддержки виджетов. Как я могу справиться без делегирования сцены?

3. Какой метод получает обратный вызов в Objective c??

4. Для Objective C и более старых проектов вы можете использовать эту функцию для перехвата URL - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options

5. @iOS. Согласно документам , это зависит от того, что вы внедрили. «Когда виджет получает взаимодействие, система активирует содержащееся приложение и передает URL в onOpenURL (выполнить:), application( :открыть:параметры:) или application ( :открыть:), в зависимости от жизненного цикла, используемого вашим приложением».

Ответ №2:

Если вы устанавливаете widgetURL или управление ссылками для пользовательского интерфейса виджета, то содержащее приложение открывается с помощью application(_:open:options:) . Вы можете указать дополнительные данные в URL, чтобы узнать источник.

Если вы не используете widgetUrl или link control, то содержащее приложение открывается с помощью application(_:continue:restorationHandler:) и userInfo имеет WidgetCenter.UserInfoKey . Это должно сообщить вам, что приложение открыто из виджета, и информацию о взаимодействии пользователя.

Комментарии:

1. Только если приложение было закрыто заранее..

Ответ №3:

Жизненный цикл SwiftUI 2

  1. Добавить widgetURL в свой вид виджета:
 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 с различными примерами виджетов, включая виджет DeepLink.

Комментарии:

1. Не вызывается openURL: (У меня реализованы делегирование приложения и удаление сцены. Есть идеи?