#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
- Добавить
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)
}
}
- Определить, открыто ли приложение с помощью глубокой ссылки в
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: (У меня реализованы делегирование приложения и удаление сцены. Есть идеи?