Authentication 快速确定初始视图
我正在尝试在SwiftUI生命周期中制作的应用程序的开始部分找到导航。根据启动时确定的设置,用户可以在三个视图中的一个视图中启动。如果用户通过推送通知打开应用程序,他们应该会看到视频视图(WrappedVideoViewController)。否则,如果他们已经登录,他们应该会看到主视图,如果没有,则会看到登录视图。我使用ContentView作为父级:Authentication 快速确定初始视图,authentication,push-notification,swiftui,Authentication,Push Notification,Swiftui,我正在尝试在SwiftUI生命周期中制作的应用程序的开始部分找到导航。根据启动时确定的设置,用户可以在三个视图中的一个视图中启动。如果用户通过推送通知打开应用程序,他们应该会看到视频视图(WrappedVideoViewController)。否则,如果他们已经登录,他们应该会看到主视图,如果没有,则会看到登录视图。我使用ContentView作为父级: import SwiftUI struct ContentView: View { @EnvironmentObject var n
import SwiftUI
struct ContentView: View {
@EnvironmentObject var notifService: NotificationService
@EnvironmentObject var authState: AuthenticationState
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
@ObservedObject var viewRouter: ViewRouter
init() {
self.viewRouter = ViewRouter.shared
}
var body: some View {
print("in ContentView body")
switch viewRouter.currentScreen {
case .home:
print("home")
return AnyView(Home(innerGradientColor: Color.homeActiveInner, outerGradientColor: Color.homeActiveOuter))
case .login:
print("login")
return
AnyView(Login()
.environmentObject(AuthenticationState.shared))
case .video:
print("video")
return AnyView(WrappedVideoViewController())
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
.environmentObject(AuthenticationState.shared)
.environmentObject(NotificationService())
}
}
我的ViewRouter类是一个ObserveObject,用于控制显示哪个屏幕。目前,我有:
//
// NavigationState.swift
// BumpCall-SwiftUI
//
// Created by Ben on 1/22/21.
//
import Foundation
import SwiftUI
enum Screen {
case home
case video
case login
}
class ViewRouter: ObservableObject {
var authState: AuthenticationState
var notifService: NotificationService
static var shared = ViewRouter(authState: AuthenticationState.shared, notifService: NotificationService.shared)
init(authState: AuthenticationState, notifService: NotificationService) {
self.authState = authState
self.notifService = notifService
if notifService.dumbData != nil {
currentScreen = .video
} else if (notifService.dumbData == nil && authState.isLoggedIn()) {
currentScreen = .home
} else {
currentScreen = .login
}
}
@Published var currentScreen: Screen
}
这很棘手,因为ViewRouter依赖于另外两个ObserveObject,我在这里试图用init()处理它们。AuthenticationState类似乎工作正常,因为在打开应用程序时,如果您登录,它会将您发送到主屏幕。但是,从通知打开也会将我发送到主屏幕。NotificationService更改didReceive响应中的ViewRouter单例:方法:
class NotificationService: NSObject, ObservableObject {
@Published var dumbData: UNNotificationResponse?
static var shared = NotificationService()
override init() {
super.init()
UNUserNotificationCenter.current().delegate = self
}
}
extension NotificationService: UNUserNotificationCenterDelegate {
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
print("presenting notification")
}
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
ViewRouter.shared.notifService.dumbData = response
print("Notification service didReceive response")
completionHandler()
}
func userNotificationCenter(_ center: UNUserNotificationCenter, openSettingsFor notification: UNNotification?) { }
}
但是单例不能更新,ContentView才会注意到。这是一个非常复杂的问题,让我困惑了好几天,任何帮助都将不胜感激。问题是
ViewRouter
init()
将被调用一次。如您所述,当用户登录时,currentScreen
将被初始化为.home
。但是,此变量以后将永远不会更改
您基本上想要的是在通知委托内将currentScreen
设置为.video
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
ViewRouter.shared.currentScreen = .video //<< here set video
print("Notification service didReceive response")
completionHandler()
}
func userNotificationCenter(center:UNUserNotificationCenter,didReceive响应:UNNotificationResponse,withCompletionHandler completionHandler:@escaping()->Void){
ViewRouter.shared.currentScreen=.video//非常感谢您,这非常好用。